From d96e1594dd378078987900819afc611bd0db19b0 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 13 Jan 2021 21:14:28 +0000 Subject: This brings in resolution and type checking of the unit-type. It is possible to assign and declare variables of unit-type which translate down to zero sized void_type_node. More work is needed to handle array and ADT types using unit-type when emiting gimple. The name+type resolution should be generic enough. --- gcc/rust/ast/rust-expr.h | 2 ++ gcc/rust/backend/rust-compile-context.h | 7 +++++-- gcc/rust/backend/rust-compile-expr.h | 15 +++++++++----- gcc/rust/backend/rust-compile-stmt.h | 15 +++++++++++++- gcc/rust/backend/rust-compile-tyty.h | 7 +++++-- gcc/rust/hir/rust-ast-lower-expr.h | 22 ++++++++++++++++++++- gcc/rust/hir/rust-ast-lower-type.h | 28 ++++++++++++++++++++++++--- gcc/rust/hir/tree/rust-hir-expr.h | 11 +++++++++++ gcc/rust/resolve/rust-ast-resolve-expr.h | 8 +++++++- gcc/rust/resolve/rust-ast-resolve-type.h | 12 +++++++++++- gcc/rust/resolve/rust-ast-resolve.cc | 12 +++++++++++- gcc/rust/resolve/rust-name-resolver.h | 8 ++++++-- gcc/rust/rust-backend.h | 2 ++ gcc/rust/rust-gcc.cc | 2 ++ gcc/rust/typecheck/rust-hir-type-check-expr.h | 16 +++++++++++++++ gcc/rust/typecheck/rust-hir-type-check-type.h | 16 +++++++++++++++ gcc/rust/typecheck/rust-hir-type-check.h | 1 + gcc/rust/typecheck/rust-tyctx.cc | 15 ++++++++++++++ gcc/rust/typecheck/rust-tyty-resolver.h | 10 ++++++++-- gcc/rust/typecheck/rust-tyty-rules.h | 5 ++++- 20 files changed, 192 insertions(+), 22 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 2dbaec8..8a1fd6e 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1345,6 +1345,8 @@ public: return tuple_elems; } + bool is_unit () const { return tuple_elems.size () == 0; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 298ff50..5a0805b 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -223,8 +223,6 @@ public: void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } - void visit (TyTy::UnitType &type) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } void visit (TyTy::FnType &type) override { gcc_unreachable (); } @@ -233,6 +231,11 @@ public: void visit (TyTy::ParamType &type) override { gcc_unreachable (); } + void visit (TyTy::UnitType &type) override + { + translated = ctx->get_backend ()->void_type (); + } + void visit (TyTy::ADTType &type) override { ::Btype *compiled_type = nullptr; diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 0370129..d38ef04 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -38,7 +38,16 @@ public: return compiler.translated; } - virtual ~CompileExpr () {} + void visit (HIR::TupleExpr &expr) + { + if (expr.is_unit ()) + { + translated = ctx->get_backend ()->unit_expression (); + return; + } + + gcc_unreachable (); + } void visit (HIR::ReturnExpr &expr) { @@ -85,10 +94,6 @@ public: return; } - printf ("have ast node id %u ref %u for expr [%s]\n", - expr.get_mappings ().get_nodeid (), ref_node_id, - expr.as_string ().c_str ()); - // these ref_node_ids will resolve to a pattern declaration but we are // interested in the definition that this refers to get the parent id Resolver::Definition def; diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h index 5f7decb..c52f605 100644 --- a/gcc/rust/backend/rust-compile-stmt.h +++ b/gcc/rust/backend/rust-compile-stmt.h @@ -71,6 +71,18 @@ public: if (!stmt.has_init_expr ()) return; + TyTy::TyBase *ty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (stmt.get_mappings ().get_hirid (), + &ty)) + { + rust_fatal_error (stmt.get_locus (), "failed to lookup var decl type"); + return; + } + + // there is an ICE in GCC for void_node + if (ty->get_kind () == TyTy::TypeKind::UNIT) + return; + Bvariable *var = nullptr; if (!ctx->lookup_var_decl (stmt.get_mappings ().get_hirid (), &var)) { @@ -79,7 +91,8 @@ public: return; } - auto *init = CompileExpr::Compile (stmt.get_init_expr (), ctx); + Bexpression *init = CompileExpr::Compile (stmt.get_init_expr (), ctx); + auto fnctx = ctx->peek_fn (); auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var, init); ctx->add_statement (s); diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index 137b74b..cd220e0 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -45,8 +45,6 @@ public: void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } - void visit (TyTy::UnitType &type) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } @@ -57,6 +55,11 @@ public: void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } + void visit (TyTy::UnitType &type) override + { + translated = backend->void_type (); + } + void visit (TyTy::FnType &type) override { Backend::Btyped_identifier receiver; diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index 51bf108..701efd5 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -132,7 +132,27 @@ public: return resolver.translated; } - virtual ~ASTLoweringExpr () {} + void visit (AST::TupleExpr &expr) + { + std::vector inner_attribs; + std::vector outer_attribs; + std::vector > tuple_elements; + for (auto &e : expr.get_tuple_elems ()) + { + HIR::Expr *t = ASTLoweringExpr::translate (e.get ()); + tuple_elements.push_back (std::unique_ptr (t)); + } + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated + = new HIR::TupleExpr (std::move (mapping), std::move (tuple_elements), + std::move (inner_attribs), + std::move (outer_attribs), expr.get_locus ()); + } void visit (AST::IfExpr &expr) { diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index 2e14ad2..fdf8f46 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -33,12 +33,34 @@ public: { ASTLoweringType resolver; type->accept_vis (resolver); + + resolver.mappings->insert_location ( + resolver.translated->get_mappings ().get_crate_num (), + resolver.translated->get_mappings ().get_hirid (), + type->get_locus_slow ()); + return resolver.translated; } - virtual ~ASTLoweringType () {} + void visit (AST::TupleType &tuple) + { + std::vector > elems; + for (auto &e : tuple.get_elems ()) + { + HIR::Type *t = ASTLoweringType::translate (e.get ()); + elems.push_back (std::unique_ptr (t)); + } + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, tuple.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + + translated = new HIR::TupleType (std::move (mapping), std::move (elems), + tuple.get_locus ()); + } - virtual void visit (AST::TypePathSegment &segment) + void visit (AST::TypePathSegment &segment) { HIR::PathIdentSegment ident (segment.get_ident_segment ().as_string ()); translated_segment @@ -47,7 +69,7 @@ public: segment.get_locus ()); } - virtual void visit (AST::TypePath &path) + void visit (AST::TypePath &path) { std::vector > translated_segments; diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 11be8b6..5d63507 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -1233,6 +1233,17 @@ public: void accept_vis (HIRVisitor &vis) override; + const std::vector > &get_tuple_elems () const + { + return tuple_elems; + } + std::vector > &get_tuple_elems () + { + return tuple_elems; + } + + bool is_unit () const { return tuple_elems.size () == 0; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 324d820..abab268 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -35,7 +35,13 @@ public: expr->accept_vis (resolver); }; - ~ResolveExpr () {} + void visit (AST::TupleExpr &expr) + { + if (expr.is_unit ()) + return; + + gcc_unreachable (); + } void visit (AST::PathInExpression &expr) { diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index 8ec3a9c..ae352b9 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -40,7 +40,17 @@ public: } }; - ~ResolveType () {} + void visit (AST::TupleType &tuple) + { + if (tuple.is_unit_type ()) + { + resolved_node = resolver->get_unit_type_node_id (); + return; + } + + // TODO see github #78 + gcc_unreachable (); + } void visit (AST::TypePath &path) { diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index d6eed93..e0b4f3a 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -113,7 +113,7 @@ Resolver::insert_builtin_types (Rib *r) Linemap::predeclared_location ()); } -std::vector & +std::vector & Resolver::get_builtin_types () { return builtins; @@ -160,6 +160,16 @@ Resolver::generate_builtins () MKBUILTIN_TYPE ("bool", builtins, rbool); MKBUILTIN_TYPE ("f32", builtins, f32); MKBUILTIN_TYPE ("f64", builtins, f64); + + // unit type () + TyTy::UnitType *unit_tyty = new TyTy::UnitType (mappings->get_next_hir_id ()); + std::vector > elems; + AST::TupleType *unit_type + = new AST::TupleType (std::move (elems), Linemap::predeclared_location ()); + builtins.push_back (unit_type); + tyctx->insert_builtin (unit_tyty->get_ref (), unit_type->get_node_id (), + unit_tyty); + set_unit_type_node_id (unit_type->get_node_id ()); } void diff --git a/gcc/rust/resolve/rust-name-resolver.h b/gcc/rust/resolve/rust-name-resolver.h index 515ebfd..4d98e7f 100644 --- a/gcc/rust/resolve/rust-name-resolver.h +++ b/gcc/rust/resolve/rust-name-resolver.h @@ -209,7 +209,7 @@ public: // these will be required for type resolution passes to // map back to tyty nodes - std::vector &get_builtin_types (); + std::vector &get_builtin_types (); void push_new_name_rib (Rib *r); void push_new_type_rib (Rib *r); @@ -232,6 +232,9 @@ public: NodeId get_global_type_node_id () { return global_type_node_id; } + void set_unit_type_node_id (NodeId id) { unit_ty_node_id = id; } + NodeId get_unit_type_node_id () { return unit_ty_node_id; } + private: Resolver (); @@ -240,12 +243,13 @@ private: Analysis::Mappings *mappings; TypeCheckContext *tyctx; - std::vector builtins; + std::vector builtins; Scope name_scope; Scope type_scope; NodeId global_type_node_id; + NodeId unit_ty_node_id; // map a AST Node to a Rib std::map name_ribs; diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index 210eff3..02c12ee 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -254,6 +254,8 @@ public: // Create a nil pointer expression. virtual Bexpression *nil_pointer_expression () = 0; + virtual Bexpression *unit_expression () = 0; + // Create a reference to a variable. virtual Bexpression *var_expression (Bvariable *var, Location) = 0; diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index bfa7609..748aa5a 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -225,6 +225,8 @@ public: return this->make_expression (null_pointer_node); } + Bexpression *unit_expression () { return this->make_expression (void_node); } + Bexpression *var_expression (Bvariable *var, Location); Bexpression *indirect_expression (Btype *, Bexpression *expr, diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index f2014a1..d7729cc 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -43,6 +43,22 @@ public: return resolver.infered; } + void visit (HIR::TupleExpr &expr) + { + if (expr.is_unit ()) + { + auto unit_node_id = resolver->get_unit_type_node_id (); + if (!context->lookup_builtin (unit_node_id, &infered)) + { + rust_error_at (expr.get_locus (), + "failed to lookup builtin unit type"); + } + return; + } + + gcc_unreachable (); + } + void visit (HIR::ReturnExpr &expr) { auto ret = context->peek_return_type (); diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index 8ff4c44..fdb4176 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -76,6 +76,22 @@ public: return resolver.translated; } + void visit (HIR::TupleType &tuple) + { + if (tuple.is_unit_type ()) + { + auto unit_node_id = resolver->get_unit_type_node_id (); + if (!context->lookup_builtin (unit_node_id, &translated)) + { + rust_error_at (tuple.get_locus (), + "failed to lookup builtin unit type"); + } + return; + } + + gcc_unreachable (); + } + void visit (HIR::TypePath &path) { // check if this is already defined or not diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index 6deecdd..3572f22 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -33,6 +33,7 @@ public: ~TypeCheckContext (); + bool lookup_builtin (NodeId id, TyTy::TyBase **type); bool lookup_builtin (std::string name, TyTy::TyBase **type); void insert_builtin (HirId id, NodeId ref, TyTy::TyBase *type); diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc index cd171d1..15b4c26 100644 --- a/gcc/rust/typecheck/rust-tyctx.cc +++ b/gcc/rust/typecheck/rust-tyctx.cc @@ -36,6 +36,21 @@ TypeCheckContext::TypeCheckContext () {} TypeCheckContext::~TypeCheckContext () {} bool +TypeCheckContext::lookup_builtin (NodeId id, TyTy::TyBase **type) +{ + auto ref_it = node_id_refs.find (id); + if (ref_it == node_id_refs.end ()) + return false; + + auto it = resolved.find (ref_it->second); + if (it == resolved.end ()) + return false; + + *type = it->second; + return true; +} + +bool TypeCheckContext::lookup_builtin (std::string name, TyTy::TyBase **type) { for (auto &builtin : builtins) diff --git a/gcc/rust/typecheck/rust-tyty-resolver.h b/gcc/rust/typecheck/rust-tyty-resolver.h index 22c3c91..3c31076 100644 --- a/gcc/rust/typecheck/rust-tyty-resolver.h +++ b/gcc/rust/typecheck/rust-tyty-resolver.h @@ -108,13 +108,19 @@ public: { auto combined = resolved_tyty->combine (it); if (combined == nullptr) - break; + { + rust_fatal_error (decl->get_locus_slow (), + "type-check resolver failed"); + break; + } resolved_tyty = combined; } // something is not inferred we need to look at all references now - if (resolved_tyty == nullptr || resolved_tyty->is_unit ()) + if (resolved_tyty == nullptr + || resolved_tyty->get_kind () == TyTy::TypeKind::INFER + || resolved_tyty->get_kind () == TyTy::TypeKind::ERROR) { rust_fatal_error (decl->get_locus_slow (), "failed to resolve type"); return false; diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 677013f..ce23fa2 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -215,7 +215,10 @@ public: return resolved; } - void visit (IntType &type) override { rust_assert (false); } + void visit (UnitType &type) override + { + resolved = new UnitType (type.get_ref ()); + } private: UnitType *base; -- cgit v1.1 From e4a2a52b35e99a40f8bd3992a6b53650908fd188 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 12 Jan 2021 17:12:00 +0000 Subject: Enforce type checking on implicit returns This change enforces strict type checkon on all ExprWithBlock. This includes unreachable tail expressions. Specific test cases have been added for context to ensure the failure cases are hit accordingly. This change also improves the diagnostic errors for mismatched types where the reference HirId was lost leading to default locations. --- gcc/rust/backend/rust-compile-context.h | 10 +- gcc/rust/backend/rust-compile-item.h | 2 +- gcc/rust/backend/rust-compile.cc | 2 +- gcc/rust/hir/rust-ast-lower-item.h | 7 +- gcc/rust/hir/rust-ast-lower-type.h | 3 +- gcc/rust/hir/rust-ast-lower.cc | 21 +++-- gcc/rust/hir/tree/rust-hir-expr.h | 9 +- gcc/rust/typecheck/rust-hir-type-check-expr.h | 94 +++++++++++++------ gcc/rust/typecheck/rust-hir-type-check-item.h | 6 ++ gcc/rust/typecheck/rust-hir-type-check-toplevel.h | 7 +- gcc/rust/typecheck/rust-hir-type-check-type.h | 1 - gcc/rust/typecheck/rust-hir-type-check.cc | 12 +-- gcc/rust/typecheck/rust-tyty-rules.h | 94 +++++++++++-------- gcc/rust/typecheck/rust-tyty.cc | 87 +++++++++++++++++- gcc/rust/typecheck/rust-tyty.h | 107 +++++++++++++++++++--- 15 files changed, 346 insertions(+), 116 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 5a0805b..fb227ac 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -239,7 +239,7 @@ public: void visit (TyTy::ADTType &type) override { ::Btype *compiled_type = nullptr; - bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; } @@ -260,7 +260,7 @@ public: void visit (TyTy::BoolType &type) override { ::Btype *compiled_type = nullptr; - bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; } @@ -268,7 +268,7 @@ public: void visit (TyTy::IntType &type) override { ::Btype *compiled_type = nullptr; - bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; } @@ -276,7 +276,7 @@ public: void visit (TyTy::UintType &type) override { ::Btype *compiled_type = nullptr; - bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; } @@ -284,7 +284,7 @@ public: void visit (TyTy::FloatType &type) override { ::Btype *compiled_type = nullptr; - bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; } diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index c5fe9a2..8c7eda5 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -246,7 +246,7 @@ public: return true; }); - if (function_body->has_expr ()) + if (function_body->has_expr () && function_body->tail_expr_reachable ()) { // the previous passes will ensure this is a valid return // dead code elimination should remove any bad trailing expressions diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 3f8a962..b394289 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -90,7 +90,7 @@ CompileBlock::visit (HIR::BlockExpr &expr) return true; }); - if (expr.has_expr ()) + if (expr.has_expr () && expr.tail_expr_reachable ()) { // the previous passes will ensure this is a valid return // dead code elimination should remove any bad trailing expressions diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index 4a5a3fe..3cf044e 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -190,15 +190,16 @@ public: = std::unique_ptr ( ASTLoweringBlock::translate (function.get_definition ().get (), &terminated)); - if (!terminated && function.has_return_type ()) - rust_error_at (function.get_definition ()->get_locus (), - "missing return"); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, function.get_node_id (), mappings->get_next_hir_id (crate_num), mappings->get_next_localdef_id (crate_num)); + mappings->insert_location (crate_num, + function_body->get_mappings ().get_hirid (), + function.get_locus ()); + auto fn = new HIR::Function (mapping, std::move (function_name), std::move (qualifiers), std::move (generic_params), diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index fdf8f46..84d09bc 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -122,10 +122,9 @@ public: } private: - ASTLoweringType () : translated (nullptr) {} + ASTLoweringType () : translated (nullptr), translated_segment (nullptr) {} HIR::Type *translated; - HIR::TypePathSegment *translated_segment; }; diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index 4f0d0d0..55c6f72 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -89,29 +89,30 @@ ASTLoweringBlock::visit (AST::BlockExpr &expr) return true; }); - HIR::ExprWithoutBlock *tail_expr = nullptr; - if (expr.has_tail_expr () && !block_did_terminate) - { - tail_expr = (HIR::ExprWithoutBlock *) ASTLoweringExpr::translate ( - expr.get_tail_expr ().get ()); - } - else if (expr.has_tail_expr () && block_did_terminate) + bool tail_reachable = expr.has_tail_expr () && !block_did_terminate; + if (expr.has_tail_expr () && block_did_terminate) { // warning unreachable tail expressions rust_warning_at (expr.get_tail_expr ()->get_locus_slow (), 0, "unreachable expression"); } + HIR::ExprWithoutBlock *tail_expr = nullptr; + if (expr.has_tail_expr ()) + { + tail_expr = (HIR::ExprWithoutBlock *) ASTLoweringExpr::translate ( + expr.get_tail_expr ().get ()); + } + auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - translated = new HIR::BlockExpr (mapping, std::move (block_stmts), std::unique_ptr (tail_expr), - std::move (inner_attribs), std::move (outer_attribs), - expr.get_locus ()); + tail_reachable, std::move (inner_attribs), + std::move (outer_attribs), expr.get_locus ()); terminated = block_did_terminate || expr.has_tail_expr (); } diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 5d63507..0d67086 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -2524,11 +2524,10 @@ class BlockExpr : public ExprWithBlock public: std::vector inner_attrs; - // bool has_statements; std::vector > statements; - // bool has_expr; std::unique_ptr expr; // inlined from Statements + bool tail_reachable; Location locus; std::string as_string () const override; @@ -2539,15 +2538,17 @@ public: // Returns whether the block contains an expression bool has_expr () const { return expr != nullptr; } + bool tail_expr_reachable () const { return tail_reachable; } + BlockExpr (Analysis::NodeMapping mappings, std::vector > block_statements, - std::unique_ptr block_expr, + std::unique_ptr block_expr, bool tail_reachable, std::vector inner_attribs, std::vector outer_attribs, Location locus) : ExprWithBlock (std::move (mappings), std::move (outer_attribs)), inner_attrs (std::move (inner_attribs)), statements (std::move (block_statements)), expr (std::move (block_expr)), - locus (locus) + tail_reachable (tail_reachable), locus (locus) {} // Copy constructor with clone diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index d7729cc..4b474ae 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -36,10 +36,13 @@ public: { TypeCheckExpr resolver (is_final_expr); expr->accept_vis (resolver); - if (resolver.infered != nullptr) - resolver.context->insert_type (expr->get_mappings ().get_hirid (), - resolver.infered); + if (resolver.infered == nullptr) + resolver.infered + = new TyTy::UnitType (expr->get_mappings ().get_hirid ()); + + resolver.context->insert_type (expr->get_mappings ().get_hirid (), + resolver.infered); return resolver.infered; } @@ -104,6 +107,10 @@ public: } infered = TyTy::TypeCheckCallExpr::go (lookup, expr); + + TyTy::InferType infer (expr.get_mappings ().get_hirid ()); + infered = infer.combine (infered); + infered->set_ref (expr.get_mappings ().get_hirid ()); } void visit (HIR::AssignmentExpr &expr) @@ -159,8 +166,9 @@ public: return; } - // FIXME this needs to be cloned for memory management later on - infered = lookup; + TyTy::InferType infer (expr.get_mappings ().get_hirid ()); + infered = infer.combine (lookup); + infered->set_ref (expr.get_mappings ().get_hirid ()); } void visit (HIR::LiteralExpr &expr) @@ -250,6 +258,10 @@ public: gcc_unreachable (); break; } + + TyTy::InferType infer (expr.get_mappings ().get_hirid ()); + infered = infer.combine (infered); + infered->set_ref (expr.get_mappings ().get_hirid ()); } void visit (HIR::ArithmeticOrLogicalExpr &expr) @@ -266,7 +278,6 @@ public: auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); infered = lhs->combine (rhs); - // FIXME this will need to turn into bool } void visit (HIR::LazyBooleanExpr &expr) @@ -281,40 +292,69 @@ public: void visit (HIR::IfExpr &expr) { TypeCheckExpr::Resolve (expr.get_if_condition ()); - TypeCheckExpr::Resolve (expr.get_if_block ()); + auto blk_expr = TypeCheckExpr::Resolve (expr.get_if_block ()); - // if without else always resolves to unit type - infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); + if (is_final_expr + && context->peek_return_type ()->get_kind () != TyTy::TypeKind::UNIT) + { + auto expected_ty = context->peek_return_type (); + infered = expected_ty->combine (blk_expr); + } } void visit (HIR::IfExprConseqElse &expr) { - // this must combine to what the type is expected - // this might be a parameter or the last expr in an if + else in a BlockExpr - // then it must resolve to fn return type - // else its a unit-type - infered = is_final_expr - ? context->peek_return_type () - : new TyTy::UnitType (expr.get_mappings ().get_hirid ()); - - TypeCheckExpr::Resolve (expr.get_if_condition (), is_final_expr); - auto if_blk_ty = TypeCheckExpr::Resolve (expr.get_if_block ()); - auto else_blk_ty = TypeCheckExpr::Resolve (expr.get_else_block ()); - - if (is_final_expr) + // check and resolve all types in the conditional var + TypeCheckExpr::Resolve (expr.get_if_condition ()); + + auto if_blk_resolved = TypeCheckExpr::Resolve (expr.get_if_block ()); + auto else_blk_resolved = TypeCheckExpr::Resolve (expr.get_else_block ()); + + TyTy::TyBase *if_block_tyty = nullptr; + if (expr.get_if_block ()->has_expr ()) + if_block_tyty + = TypeCheckExpr::Resolve (expr.get_if_block ()->expr.get ()); + else + if_block_tyty = if_blk_resolved; + + TyTy::TyBase *else_block_tyty = nullptr; + if (expr.get_else_block ()->has_expr ()) + else_block_tyty + = TypeCheckExpr::Resolve (expr.get_else_block ()->expr.get ()); + else + else_block_tyty = else_blk_resolved; + + if (context->peek_return_type ()->get_kind () != TyTy::TypeKind::UNIT) { - infered = infered->combine (if_blk_ty); - infered = infered->combine (else_blk_ty); + // this must combine to what the type is expected + // this might be a parameter or the last expr in an if + else in a + // BlockExpr then it must resolve to fn return type else its a unit-type + auto expected_ty + = is_final_expr + ? context->peek_return_type () + : new TyTy::UnitType (expr.get_mappings ().get_hirid ()); + + auto if_blk_combined = expected_ty->combine (if_block_tyty); + auto else_blk_combined = expected_ty->combine (else_block_tyty); + + infered = if_blk_combined->combine (else_blk_combined); } } void visit (HIR::IfExprConseqIf &expr) { TypeCheckExpr::Resolve (expr.get_if_condition ()); - TypeCheckExpr::Resolve (expr.get_if_block ()); - TypeCheckExpr::Resolve (expr.get_conseq_if_expr ()); + auto if_blk = TypeCheckExpr::Resolve (expr.get_if_block ()); + auto elif_blk = TypeCheckExpr::Resolve (expr.get_conseq_if_expr ()); - infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); + if (is_final_expr + && context->peek_return_type ()->get_kind () != TyTy::TypeKind::UNIT) + { + auto expected_ty = context->peek_return_type (); + + infered = expected_ty->combine (if_blk); + infered = infered->combine (elif_blk); + } } void visit (HIR::BlockExpr &expr); diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index 62320a6..20f5adb 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -85,6 +85,12 @@ public: context->push_return_type (resolve_fn_type.go ()); TypeCheckExpr::Resolve (function.function_body.get ()); + if (function.function_body->has_expr ()) + { + auto resolved + = TypeCheckExpr::Resolve (function.function_body->expr.get ()); + context->peek_return_type ()->combine (resolved); + } context->pop_return_type (); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index 34e7020..ecee372 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -83,7 +83,12 @@ public: if (!function.has_function_return_type ()) ret_type = new TyTy::UnitType (function.get_mappings ().get_hirid ()); else - ret_type = TypeCheckType::Resolve (function.return_type.get ()); + { + TyTy::InferType infer (function.get_mappings ().get_hirid ()); + auto resolved = TypeCheckType::Resolve (function.return_type.get ()); + ret_type = infer.combine (resolved); + ret_type->set_ref (function.return_type->get_mappings ().get_hirid ()); + } std::vector params; for (auto ¶m : function.function_params) diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index fdb4176..1a01774 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -119,7 +119,6 @@ public: // this might be a struct type (TyTy::ADT) reference // TODO - printf ("UNREACHABLE %s\n", path.as_string ().c_str ()); gcc_unreachable (); } diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index 8fa6714..a5b9b8b 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -47,7 +47,7 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) bool is_final_stmt = expr.is_final_stmt (s); bool is_final_expr = is_final_stmt && !expr.has_expr (); - auto infered = TypeCheckStmt::Resolve (s, is_final_stmt); + auto infered = TypeCheckStmt::Resolve (s, is_final_expr); if (is_final_expr) { delete block_tyty; @@ -57,13 +57,10 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) return true; }); + // tail expression must be checked as part of the caller since + // the result of this is very dependant on what we expect it to be if (expr.has_expr ()) - { - auto tail_tyty = TypeCheckExpr::Resolve (expr.expr.get (), true); - - delete block_tyty; - block_tyty = tail_tyty; - } + TypeCheckExpr::Resolve (expr.expr.get ()); // now that the stmts have been resolved we must resolve the block of locals // and make sure the variables have been resolved @@ -74,7 +71,6 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) rust_fatal_error (expr.get_locus (), "failed to lookup locals per block"); return; } - TyTyResolver::Resolve (rib, mappings, resolver, context); infered = block_tyty; diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index ce23fa2..3bea57d 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -38,7 +38,7 @@ public: Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_fatal_error (def_locus, "declared here"); + rust_error_at (def_locus, "declared here"); } virtual void visit (ADTType &type) override @@ -47,7 +47,7 @@ public: Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_fatal_error (def_locus, "declared here"); + rust_error_at (def_locus, "declared here"); } virtual void visit (InferType &type) override @@ -56,7 +56,7 @@ public: Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_fatal_error (def_locus, "declared here"); + rust_error_at (def_locus, "declared here"); } virtual void visit (FnType &type) override @@ -65,7 +65,7 @@ public: Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_fatal_error (def_locus, "declared here"); + rust_error_at (def_locus, "declared here"); } virtual void visit (ParamType &type) override @@ -74,7 +74,7 @@ public: Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_fatal_error (def_locus, "declared here"); + rust_error_at (def_locus, "declared here"); } virtual void visit (ArrayType &type) override @@ -83,7 +83,7 @@ public: Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_fatal_error (def_locus, "declared here"); + rust_error_at (def_locus, "declared here"); } virtual void visit (BoolType &type) override @@ -92,7 +92,7 @@ public: Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_fatal_error (def_locus, "declared here"); + rust_error_at (def_locus, "declared here"); } virtual void visit (IntType &type) override @@ -101,7 +101,7 @@ public: Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_fatal_error (def_locus, "declared here"); + rust_error_at (def_locus, "declared here"); } virtual void visit (UintType &type) override @@ -110,7 +110,7 @@ public: Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_fatal_error (def_locus, "declared here"); + rust_error_at (def_locus, "declared here"); } virtual void visit (FloatType &type) override @@ -119,7 +119,7 @@ public: Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_fatal_error (def_locus, "declared here"); + rust_error_at (def_locus, "declared here"); } virtual void visit (ErrorType &type) override @@ -128,7 +128,7 @@ public: Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_fatal_error (def_locus, "declared here"); + rust_error_at (def_locus, "declared here"); } virtual void visit (StructFieldType &type) override @@ -137,13 +137,13 @@ public: Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_fatal_error (def_locus, "declared here"); + rust_error_at (def_locus, "declared here"); } protected: BaseRules (TyBase *base) : mappings (Analysis::Mappings::get ()), base (base), - resolved (new ErrorType (base->get_ref ())) + resolved (new ErrorType (base->get_ref (), base->get_ref ())) {} Analysis::Mappings *mappings; @@ -164,25 +164,23 @@ public: // we are an inference variable so this means we can take the other as the // type - void visit (UnitType &type) override - { - resolved = new UnitType (type.get_ref ()); - } + void visit (InferType &type) override { resolved = type.clone (); } - void visit (BoolType &type) override - { - resolved = new BoolType (type.get_ref ()); - } + void visit (UnitType &type) override { resolved = type.clone (); } - void visit (IntType &type) override - { - resolved = new IntType (type.get_ref (), type.get_kind ()); - } + void visit (BoolType &type) override { resolved = type.clone (); } - void visit (UintType &type) override - { - resolved = new UintType (type.get_ref (), type.get_kind ()); - } + void visit (IntType &type) override { resolved = type.clone (); } + + void visit (UintType &type) override { resolved = type.clone (); } + + void visit (FloatType &type) override { resolved = type.clone (); } + + void visit (ParamType &type) override { resolved = type.clone (); } + + void visit (ArrayType &type) override { resolved = type.clone (); } + + void visit (ADTType &type) override { resolved = type.clone (); } private: InferType *base; @@ -217,7 +215,7 @@ public: void visit (UnitType &type) override { - resolved = new UnitType (type.get_ref ()); + resolved = new UnitType (type.get_ref (), type.get_ty_ref ()); } private: @@ -280,8 +278,8 @@ public: return; } - resolved - = new ArrayType (type.get_ref (), type.get_capacity (), base_resolved); + resolved = new ArrayType (type.get_ref (), type.get_ty_ref (), + type.get_capacity (), base_resolved); } private: @@ -301,7 +299,7 @@ public: void visit (BoolType &type) override { - resolved = new BoolType (type.get_ref ()); + resolved = new BoolType (type.get_ref (), type.get_ty_ref ()); } private: @@ -321,8 +319,14 @@ public: void visit (IntType &type) override { - // FIXME we should look at the IntTypeKind and check if i8 vs i16 etc.. - resolved = new IntType (type.get_ref (), type.get_kind ()); + if (type.get_kind () != base->get_kind ()) + { + BaseRules::visit (type); + return; + } + + resolved + = new IntType (type.get_ref (), type.get_ty_ref (), type.get_kind ()); } private: @@ -342,8 +346,14 @@ public: void visit (UintType &type) override { - // FIXME we should look at the IntTypeKind and check if u8 vs u16 etc.. - resolved = new UintType (type.get_ref (), type.get_kind ()); + if (type.get_kind () != base->get_kind ()) + { + BaseRules::visit (type); + return; + } + + resolved + = new UintType (type.get_ref (), type.get_ty_ref (), type.get_kind ()); } private: @@ -363,8 +373,14 @@ public: void visit (FloatType &type) override { - // FIXME we should look at the FloatKind and respect it - resolved = new FloatType (type.get_ref (), type.get_kind ()); + if (type.get_kind () != base->get_kind ()) + { + BaseRules::visit (type); + return; + } + + resolved + = new FloatType (type.get_ref (), type.get_ty_ref (), type.get_kind ()); } private: diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 033f839..6696aa7 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -44,6 +44,12 @@ UnitType::combine (TyBase *other) return r.combine (other); } +TyBase * +UnitType::clone () +{ + return new UnitType (get_ref (), get_ty_ref ()); +} + void InferType::accept_vis (TyVisitor &vis) { @@ -53,7 +59,7 @@ InferType::accept_vis (TyVisitor &vis) std::string InferType::as_string () const { - return "[_]"; + return "?"; } TyBase * @@ -63,6 +69,12 @@ InferType::combine (TyBase *other) return r.combine (other); } +TyBase * +InferType::clone () +{ + return new InferType (get_ref (), get_ty_ref ()); +} + void ErrorType::accept_vis (TyVisitor &vis) { @@ -78,10 +90,17 @@ ErrorType::as_string () const TyBase * ErrorType::combine (TyBase *other) { + // FIXME // rust_error_at (); return this; } +TyBase * +ErrorType::clone () +{ + return new ErrorType (get_ref ()); +} + void StructFieldType::accept_vis (TyVisitor &vis) { @@ -101,6 +120,13 @@ StructFieldType::combine (TyBase *other) return r.combine (other); } +TyBase * +StructFieldType::clone () +{ + return new StructFieldType (get_ref (), get_ty_ref (), get_name (), + get_field_type ()->clone ()); +} + void ADTType::accept_vis (TyVisitor &vis) { @@ -123,6 +149,16 @@ ADTType::combine (TyBase *other) return nullptr; } +TyBase * +ADTType::clone () +{ + std::vector cloned_fields; + for (auto &f : fields) + cloned_fields.push_back ((StructFieldType *) f->clone ()); + + return new ADTType (get_ref (), get_ty_ref (), get_name (), cloned_fields); +} + void FnType::accept_vis (TyVisitor &vis) { @@ -150,6 +186,17 @@ FnType::combine (TyBase *other) return r.combine (other); } +TyBase * +FnType::clone () +{ + std::vector cloned_params; + for (auto &p : params) + cloned_params.push_back ((ParamType *) p->clone ()); + + return new FnType (get_ref (), get_ty_ref (), cloned_params, + get_return_type ()->clone ()); +} + void ParamType::accept_vis (TyVisitor &vis) { @@ -169,6 +216,13 @@ ParamType::combine (TyBase *other) return r.combine (other); } +TyBase * +ParamType::clone () +{ + return new ParamType (get_ref (), get_ty_ref (), get_identifier (), + get_base_type ()->clone ()); +} + void ArrayType::accept_vis (TyVisitor &vis) { @@ -188,6 +242,13 @@ ArrayType::combine (TyBase *other) return r.combine (other); } +TyBase * +ArrayType::clone () +{ + return new ArrayType (get_ref (), get_ty_ref (), get_capacity (), + get_type ()->clone ()); +} + void BoolType::accept_vis (TyVisitor &vis) { @@ -207,6 +268,12 @@ BoolType::combine (TyBase *other) return r.combine (other); } +TyBase * +BoolType::clone () +{ + return new BoolType (get_ref (), get_ty_ref ()); +} + void IntType::accept_vis (TyVisitor &vis) { @@ -240,6 +307,12 @@ IntType::combine (TyBase *other) return r.combine (other); } +TyBase * +IntType::clone () +{ + return new IntType (get_ref (), get_ty_ref (), get_kind ()); +} + void UintType::accept_vis (TyVisitor &vis) { @@ -273,6 +346,12 @@ UintType::combine (TyBase *other) return r.combine (other); } +TyBase * +UintType::clone () +{ + return new UintType (get_ref (), get_ty_ref (), get_kind ()); +} + void FloatType::accept_vis (TyVisitor &vis) { @@ -300,6 +379,12 @@ FloatType::combine (TyBase *other) return r.combine (other); } +TyBase * +FloatType::clone () +{ + return new FloatType (get_ref (), get_ty_ref (), get_kind ()); +} + void TypeCheckCallExpr::visit (FnType &type) { diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index be7ec0c..2a6d2a8 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -54,6 +54,12 @@ public: HirId get_ref () const { return ref; } + void set_ref (HirId id) { ref = id; } + + HirId get_ty_ref () const { return ty_ref; } + + void set_ty_ref (HirId id) { ty_ref = id; } + virtual void accept_vis (TyVisitor &vis) = 0; virtual std::string as_string () const = 0; @@ -64,17 +70,24 @@ public: TypeKind get_kind () const { return kind; } + virtual TyBase *clone () = 0; + protected: - TyBase (HirId ref, TypeKind kind) : kind (kind), ref (ref) {} + TyBase (HirId ref, HirId ty_ref, TypeKind kind) + : kind (kind), ref (ref), ty_ref (ty_ref) + {} TypeKind kind; HirId ref; + HirId ty_ref; }; class InferType : public TyBase { public: - InferType (HirId ref) : TyBase (ref, TypeKind::INFER) {} + InferType (HirId ref) : TyBase (ref, ref, TypeKind::INFER) {} + + InferType (HirId ref, HirId ty_ref) : TyBase (ref, ty_ref, TypeKind::INFER) {} void accept_vis (TyVisitor &vis) override; @@ -83,12 +96,16 @@ public: std::string as_string () const override; TyBase *combine (TyBase *other) override; + + TyBase *clone () final override; }; class ErrorType : public TyBase { public: - ErrorType (HirId ref) : TyBase (ref, TypeKind::ERROR) {} + ErrorType (HirId ref) : TyBase (ref, ref, TypeKind::ERROR) {} + + ErrorType (HirId ref, HirId ty_ref) : TyBase (ref, ty_ref, TypeKind::ERROR) {} void accept_vis (TyVisitor &vis) override; @@ -97,12 +114,16 @@ public: std::string as_string () const override; TyBase *combine (TyBase *other) override; + + TyBase *clone () final override; }; class UnitType : public TyBase { public: - UnitType (HirId ref) : TyBase (ref, TypeKind::UNIT) {} + UnitType (HirId ref) : TyBase (ref, ref, TypeKind::UNIT) {} + + UnitType (HirId ref, HirId ty_ref) : TyBase (ref, ty_ref, TypeKind::UNIT) {} void accept_vis (TyVisitor &vis) override; @@ -111,13 +132,19 @@ public: std::string as_string () const override; TyBase *combine (TyBase *other) override; + + TyBase *clone () final override; }; class StructFieldType : public TyBase { public: StructFieldType (HirId ref, std::string name, TyBase *ty) - : TyBase (ref, TypeKind::FIELD), name (name), ty (ty) + : TyBase (ref, ref, TypeKind::FIELD), name (name), ty (ty) + {} + + StructFieldType (HirId ref, HirId ty_ref, std::string name, TyBase *ty) + : TyBase (ref, ty_ref, TypeKind::FIELD), name (name), ty (ty) {} void accept_vis (TyVisitor &vis) override; @@ -132,6 +159,8 @@ public: TyBase *get_field_type () { return ty; } + TyBase *clone () final override; + private: std::string name; TyBase *ty; @@ -142,7 +171,13 @@ class ADTType : public TyBase public: ADTType (HirId ref, std::string identifier, std::vector fields) - : TyBase (ref, TypeKind::ADT), identifier (identifier), fields (fields) + : TyBase (ref, ref, TypeKind::ADT), identifier (identifier), fields (fields) + {} + + ADTType (HirId ref, HirId ty_ref, std::string identifier, + std::vector fields) + : TyBase (ref, ty_ref, TypeKind::ADT), identifier (identifier), + fields (fields) {} void accept_vis (TyVisitor &vis) override; @@ -155,6 +190,8 @@ public: size_t num_fields () const { return fields.size (); } + std::string get_name () const { return identifier; } + StructFieldType *get_field (size_t index) { return fields.at (index); } StructFieldType *get_field (const std::string &lookup) @@ -167,6 +204,8 @@ public: return nullptr; } + TyBase *clone () final override; + private: std::string identifier; std::vector fields; @@ -176,7 +215,12 @@ class ParamType : public TyBase { public: ParamType (HirId ref, std::string identifier, TyBase *type) - : TyBase (ref, TypeKind::PARAM), identifier (identifier), type (type) + : TyBase (ref, ref, TypeKind::PARAM), identifier (identifier), type (type) + {} + + ParamType (HirId ref, HirId ty_ref, std::string identifier, TyBase *type) + : TyBase (ref, ty_ref, TypeKind::PARAM), identifier (identifier), + type (type) {} void accept_vis (TyVisitor &vis) override; @@ -189,6 +233,8 @@ public: TyBase *get_base_type () { return type; } + TyBase *clone () final override; + private: std::string identifier; TyBase *type; @@ -198,7 +244,12 @@ class FnType : public TyBase { public: FnType (HirId ref, std::vector params, TyBase *type) - : TyBase (ref, TypeKind::FNDEF), params (params), type (type) + : TyBase (ref, ref, TypeKind::FNDEF), params (params), type (type) + {} + + FnType (HirId ref, HirId ty_ref, std::vector params, + TyBase *type) + : TyBase (ref, ty_ref, TypeKind::FNDEF), params (params), type (type) {} void accept_vis (TyVisitor &vis) override; @@ -215,6 +266,8 @@ public: TyBase *get_return_type () { return type; } + TyBase *clone () final override; + private: std::vector params; TyBase *type; @@ -224,7 +277,11 @@ class ArrayType : public TyBase { public: ArrayType (HirId ref, size_t capacity, TyBase *type) - : TyBase (ref, TypeKind::ARRAY), capacity (capacity), type (type) + : TyBase (ref, ref, TypeKind::ARRAY), capacity (capacity), type (type) + {} + + ArrayType (HirId ref, HirId ty_ref, size_t capacity, TyBase *type) + : TyBase (ref, ty_ref, TypeKind::ARRAY), capacity (capacity), type (type) {} void accept_vis (TyVisitor &vis) override; @@ -237,6 +294,8 @@ public: TyBase *get_type () { return type; } + TyBase *clone () final override; + private: size_t capacity; TyBase *type; @@ -245,13 +304,17 @@ private: class BoolType : public TyBase { public: - BoolType (HirId ref) : TyBase (ref, TypeKind::BOOL) {} + BoolType (HirId ref) : TyBase (ref, ref, TypeKind::BOOL) {} + + BoolType (HirId ref, HirId ty_ref) : TyBase (ref, ty_ref, TypeKind::BOOL) {} void accept_vis (TyVisitor &vis) override; std::string as_string () const override; TyBase *combine (TyBase *other) override; + + TyBase *clone () final override; }; class IntType : public TyBase @@ -267,7 +330,11 @@ public: }; IntType (HirId ref, IntKind kind) - : TyBase (ref, TypeKind::INT), int_kind (kind) + : TyBase (ref, ref, TypeKind::INT), int_kind (kind) + {} + + IntType (HirId ref, HirId ty_ref, IntKind kind) + : TyBase (ref, ty_ref, TypeKind::INT), int_kind (kind) {} void accept_vis (TyVisitor &vis) override; @@ -278,6 +345,8 @@ public: IntKind get_kind () const { return int_kind; } + TyBase *clone () final override; + private: IntKind int_kind; }; @@ -295,7 +364,11 @@ public: }; UintType (HirId ref, UintKind kind) - : TyBase (ref, TypeKind::UINT), uint_kind (kind) + : TyBase (ref, ref, TypeKind::UINT), uint_kind (kind) + {} + + UintType (HirId ref, HirId ty_ref, UintKind kind) + : TyBase (ref, ty_ref, TypeKind::UINT), uint_kind (kind) {} void accept_vis (TyVisitor &vis) override; @@ -306,6 +379,8 @@ public: UintKind get_kind () const { return uint_kind; } + TyBase *clone () final override; + private: UintKind uint_kind; }; @@ -320,7 +395,11 @@ public: }; FloatType (HirId ref, FloatKind kind) - : TyBase (ref, TypeKind::FLOAT), float_kind (kind) + : TyBase (ref, ref, TypeKind::FLOAT), float_kind (kind) + {} + + FloatType (HirId ref, HirId ty_ref, FloatKind kind) + : TyBase (ref, ty_ref, TypeKind::FLOAT), float_kind (kind) {} void accept_vis (TyVisitor &vis) override; @@ -331,6 +410,8 @@ public: FloatKind get_kind () const { return float_kind; } + TyBase *clone () final override; + private: FloatKind float_kind; }; -- cgit v1.1 From b06df5d4a95ec728ade9230bec945d5d3661f87d Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 16 Jan 2021 17:25:12 +0000 Subject: This adds supports for tuples More testing is required but this adds tuples apart from TupleStructs which are parsed as CallExpr. This will be the primitives required to finish that work. --- gcc/rust/backend/rust-compile-context.h | 32 +++++++++++++-- gcc/rust/backend/rust-compile-expr.h | 24 ++++++++++- gcc/rust/hir/tree/rust-hir-type.h | 6 +++ gcc/rust/resolve/rust-ast-resolve-expr.h | 3 +- gcc/rust/resolve/rust-ast-resolve-type.h | 22 ++++------ gcc/rust/typecheck/rust-hir-type-check-expr.h | 20 ++++++++- gcc/rust/typecheck/rust-hir-type-check-type.h | 20 ++++++++- gcc/rust/typecheck/rust-tyty-rules.h | 59 +++++++++++++++++++++++++++ gcc/rust/typecheck/rust-tyty.cc | 3 +- gcc/rust/typecheck/rust-tyty.h | 3 ++ 10 files changed, 170 insertions(+), 22 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index fb227ac..5288e51 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -238,10 +238,34 @@ public: void visit (TyTy::ADTType &type) override { - ::Btype *compiled_type = nullptr; - bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); - rust_assert (ok); - translated = compiled_type; + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &translated); + if (ok) + return; + + // create implicit struct + std::vector fields; + for (size_t i = 0; i < type.num_fields (); i++) + { + TyTy::StructFieldType *field = type.get_field (i); + Btype *compiled_field_ty + = TyTyCompile::compile (ctx->get_backend (), + field->get_field_type ()); + + Backend::Btyped_identifier f (field->get_name (), compiled_field_ty, + ctx->get_mappings ()->lookup_location ( + type.get_ty_ref ())); + fields.push_back (std::move (f)); + } + + Btype *struct_type_record = ctx->get_backend ()->struct_type (fields); + Btype *named_struct + = ctx->get_backend ()->named_type (type.get_name (), struct_type_record, + ctx->get_mappings ()->lookup_location ( + type.get_ty_ref ())); + + ctx->push_type (named_struct); + ctx->insert_compiled_type (type.get_ty_ref (), named_struct); + translated = named_struct; } void visit (TyTy::ArrayType &type) override diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index d38ef04..0d3d9e8 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -46,7 +46,29 @@ public: return; } - gcc_unreachable (); + TyTy::TyBase *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &tyty)) + { + rust_fatal_error (expr.get_locus (), + "did not resolve type for this TupleExpr"); + return; + } + + Btype *tuple_type = TyTyResolveCompile::compile (ctx, tyty); + rust_assert (tuple_type != nullptr); + + // this assumes all fields are in order from type resolution + std::vector vals; + for (auto &elem : expr.get_tuple_elems ()) + { + auto e = CompileExpr::Compile (elem.get (), ctx); + vals.push_back (e); + } + + translated + = ctx->get_backend ()->constructor_expression (tuple_type, vals, + expr.get_locus ()); } void visit (HIR::ReturnExpr &expr) diff --git a/gcc/rust/hir/tree/rust-hir-type.h b/gcc/rust/hir/tree/rust-hir-type.h index f8c851c..fc369c3 100644 --- a/gcc/rust/hir/tree/rust-hir-type.h +++ b/gcc/rust/hir/tree/rust-hir-type.h @@ -393,6 +393,12 @@ public: void accept_vis (HIRVisitor &vis) override; + std::vector > &get_elems () { return elems; } + const std::vector > &get_elems () const + { + return elems; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index abab268..83fb935 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -40,7 +40,8 @@ public: if (expr.is_unit ()) return; - gcc_unreachable (); + for (auto &elem : expr.get_tuple_elems ()) + ResolveExpr::go (elem.get (), expr.get_node_id ()); } void visit (AST::PathInExpression &expr) diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index ae352b9..20fb0b6 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -31,13 +31,7 @@ public: static void go (AST::Type *type, NodeId parent) { ResolveType resolver (parent); - type->accept_vis (resolver); - if (resolver.resolved_node == UNKNOWN_NODEID) - { - rust_error_at (resolver.locus, "failed to resolve type %s", - type->as_string ().c_str ()); - } }; void visit (AST::TupleType &tuple) @@ -48,21 +42,23 @@ public: return; } - // TODO see github #78 - gcc_unreachable (); + for (auto &elem : tuple.get_elems ()) + ResolveType::go (elem.get (), tuple.get_node_id ()); } void visit (AST::TypePath &path) { // this will need changed to handle mod/crate/use globs and look // at the segments in granularity - if (resolver->get_type_scope ().lookup (path.as_string (), &resolved_node)) + if (!resolver->get_type_scope ().lookup (path.as_string (), &resolved_node)) { - resolver->insert_resolved_type (path.get_node_id (), resolved_node); - resolver->insert_new_definition (path.get_node_id (), - Definition{path.get_node_id (), - parent}); + rust_error_at (path.get_locus (), "failed to resolve TypePath: %s", + path.as_string ().c_str ()); + return; } + resolver->insert_resolved_type (path.get_node_id (), resolved_node); + resolver->insert_new_definition (path.get_node_id (), + Definition{path.get_node_id (), parent}); } void visit (AST::ArrayType &type) diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 4b474ae..19c6ed4 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -59,7 +59,25 @@ public: return; } - gcc_unreachable (); + size_t index = 0; + std::string identifier = "("; + std::vector fields; + for (auto &elem : expr.get_tuple_elems ()) + { + auto field_ty = TypeCheckExpr::Resolve (elem.get ()); + identifier += field_ty->as_string (); + if ((index + 1) < expr.get_tuple_elems ().size ()) + identifier += ","; + + auto field_tyty + = new TyTy::StructFieldType (elem->get_mappings ().get_hirid (), + std::to_string (index), field_ty); + fields.push_back (field_tyty); + index++; + } + identifier += ")"; + infered = new TyTy::ADTType (expr.get_mappings ().get_hirid (), identifier, + fields); } void visit (HIR::ReturnExpr &expr) diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index 1a01774..8b9a77c 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -89,7 +89,25 @@ public: return; } - gcc_unreachable (); + size_t index = 0; + std::string identifier = "("; + std::vector fields; + for (auto &elem : tuple.get_elems ()) + { + auto field_ty = TypeCheckType::Resolve (elem.get ()); + identifier += field_ty->as_string (); + if ((index + 1) < tuple.get_elems ().size ()) + identifier += ","; + + auto field_tyty + = new TyTy::StructFieldType (elem->get_mappings ().get_hirid (), + std::to_string (index), field_ty); + fields.push_back (field_tyty); + index++; + } + identifier += ")"; + translated = new TyTy::ADTType (tuple.get_mappings ().get_hirid (), + identifier, fields); } void visit (HIR::TypePath &path) diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 3bea57d..5353004 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -198,6 +198,16 @@ public: return resolved; } + void visit (StructFieldType &type) + { + TyBase *ty = base->get_field_type ()->combine (type.get_field_type ()); + if (ty == nullptr) + return; + + resolved = new TyTy::StructFieldType (type.get_ref (), type.get_ty_ref (), + type.get_name (), ty); + } + private: StructFieldType *base; }; @@ -387,6 +397,55 @@ private: FloatType *base; }; +class ADTRules : protected BaseRules +{ +public: + ADTRules (ADTType *base) : BaseRules (base), base (base) {} + + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + return resolved; + } + + void visit (ADTType &type) + { + if (base->num_fields () != type.num_fields ()) + { + BaseRules::visit (type); + return; + } + + if (base->get_name ().compare (type.get_name ()) != 0) + { + BaseRules::visit (type); + return; + } + + std::vector fields; + for (size_t i = 0; i < type.num_fields (); ++i) + { + TyTy::StructFieldType *base_field = base->get_field (i); + TyTy::StructFieldType *other_field = type.get_field (i); + + TyBase *combined = base_field->combine (other_field); + if (combined == nullptr) + { + BaseRules::visit (type); + return; + } + + fields.push_back ((TyTy::StructFieldType *) combined); + } + + resolved = new TyTy::ADTType (type.get_ref (), type.get_ty_ref (), + type.get_name (), fields); + } + +private: + ADTType *base; +}; + } // namespace TyTy } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 6696aa7..e007c1f 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -146,7 +146,8 @@ ADTType::as_string () const TyBase * ADTType::combine (TyBase *other) { - return nullptr; + ADTRules r (this); + return r.combine (other); } TyBase * diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 2a6d2a8..1e529bd 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -206,6 +206,9 @@ public: TyBase *clone () final override; + std::vector &get_fields () { return fields; } + const std::vector &get_fields () const { return fields; } + private: std::string identifier; std::vector fields; -- cgit v1.1 From a79e3b31be51d16c6dcc87722d35fe8cc3227355 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 16 Jan 2021 18:14:02 +0000 Subject: grouped expr wip --- gcc/rust/resolve/rust-ast-resolve-expr.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'gcc/rust') diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 83fb935..58de087 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -182,6 +182,11 @@ public: }); } + void visit (AST::GroupedExpr &expr) + { + ResolveExpr::go (expr.get_expr_in_parens ().get (), expr.get_node_id ()); + } + private: ResolveExpr (NodeId parent) : ResolverBase (parent) {} }; -- cgit v1.1 From 7066c0eca18f99aca3e88a08b2aaf71d970d0ab6 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 16 Jan 2021 18:26:36 +0000 Subject: Support GroupedExpr's This makes the expression handling support exprs within parens. Such as: x = (2*a) + 3; --- gcc/rust/backend/rust-compile-expr.h | 5 +++++ gcc/rust/hir/rust-ast-lower-expr.h | 19 +++++++++++++++++++ gcc/rust/hir/tree/rust-hir-expr.h | 6 ++++++ gcc/rust/typecheck/rust-hir-type-check-expr.h | 5 +++++ 4 files changed, 35 insertions(+) (limited to 'gcc/rust') diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 0d3d9e8..682ff79 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -428,6 +428,11 @@ public: struct_expr.get_locus ()); } + void visit (HIR::GroupedExpr &expr) + { + translated = CompileExpr::Compile (expr.get_expr_in_parens ().get (), ctx); + } + private: CompileExpr (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {} diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index 701efd5..1003e8c 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -525,6 +525,25 @@ public: inner_attribs, outer_attribs); } + void visit (AST::GroupedExpr &expr) + { + std::vector inner_attribs; + std::vector outer_attribs; + + HIR::Expr *paren_expr + = ASTLoweringExpr::translate (expr.get_expr_in_parens ().get ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated + = new HIR::GroupedExpr (mapping, std::unique_ptr (paren_expr), + std::move (inner_attribs), + std::move (outer_attribs), expr.get_locus ()); + } + private: ASTLoweringExpr () : translated (nullptr), translated_array_elems (nullptr), terminated (false) diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 0d67086..bb8499a 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -880,6 +880,12 @@ public: void accept_vis (HIRVisitor &vis) override; + std::unique_ptr &get_expr_in_parens () + { + rust_assert (expr_in_parens != nullptr); + return expr_in_parens; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 19c6ed4..dd3c8b9 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -435,6 +435,11 @@ public: infered = TypeCheckStructExpr::Resolve (&struct_expr); } + void visit (HIR::GroupedExpr &expr) + { + infered = TypeCheckExpr::Resolve (expr.get_expr_in_parens ().get ()); + } + private: TypeCheckExpr (bool is_final_expr) : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr), -- cgit v1.1 From 659ade1611568da5d91a0d6a2d76871cce658ff7 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 16 Jan 2021 14:24:56 +0000 Subject: Handle forward references in backend compilation We must ensure the backend can support compilation of things declared lexically after they are referenced. This scans the toplevel except functions which are handled as we reference them. To make that generic enough for all toplevel items will be a move to query based compilation which still needs planning. --- gcc/rust/backend/rust-compile-item.h | 13 ++++++++++--- gcc/rust/backend/rust-compile.cc | 7 +++++-- 2 files changed, 15 insertions(+), 5 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index 8c7eda5..a367ac7 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -31,9 +31,9 @@ namespace Compile { class CompileItem : public HIRCompileBase { public: - static void compile (HIR::Item *item, Context *ctx) + static void compile (HIR::Item *item, Context *ctx, bool compile_fns = true) { - CompileItem compiler (ctx); + CompileItem compiler (ctx, compile_fns); item->accept_vis (compiler); } @@ -116,6 +116,9 @@ public: void visit (HIR::Function &function) { + if (!compile_fns) + return; + // items can be forward compiled which means we may not need to invoke this // code Bfunction *lookup = nullptr; @@ -277,7 +280,11 @@ public: } private: - CompileItem (Context *ctx) : HIRCompileBase (ctx) {} + CompileItem (Context *ctx, bool compile_fns) + : HIRCompileBase (ctx), compile_fns (compile_fns) + {} + + bool compile_fns; }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index b394289..772d975 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -41,8 +41,11 @@ CompileCrate::Compile (HIR::Crate &crate, Context *ctx) void CompileCrate::go () { - for (auto it = crate.items.begin (); it != crate.items.end (); it++) - CompileItem::compile (it->get (), ctx); + for (auto &item : crate.items) + CompileItem::compile (item.get (), ctx, false); + + for (auto &item : crate.items) + CompileItem::compile (item.get (), ctx, true); } // rust-compile-block.h -- cgit v1.1 From 02132139efa60954c3f9d5aeb4d87210066b1b58 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 16 Jan 2021 14:34:06 +0000 Subject: Fix the naming of VAR_DECLS within gimple nodes. This was using LetStmt->Pattern.as_string which included mut in the string dump. This makes the gimple nodes harder to debug as the name is (mut a) insteaad of a for example. --- gcc/rust/backend/rust-compile-var-decl.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h index be3141a..cf73820 100644 --- a/gcc/rust/backend/rust-compile-var-decl.h +++ b/gcc/rust/backend/rust-compile-var-decl.h @@ -42,24 +42,33 @@ public: void visit (HIR::LetStmt &stmt) { + locus = stmt.get_locus (); TyTy::TyBase *resolved_type = nullptr; bool ok = ctx->get_tyctx ()->lookup_type (stmt.get_mappings ().get_hirid (), &resolved_type); rust_assert (ok); - ::Btype *translated_type = TyTyResolveCompile::compile (ctx, resolved_type); + translated_type = TyTyResolveCompile::compile (ctx, resolved_type); + stmt.get_pattern ()->accept_vis (*this); + } - translated = ctx->get_backend ()->local_variable ( - fndecl, stmt.get_pattern ()->as_string (), translated_type, - NULL /*decl_var*/, false /*address_taken*/, stmt.get_locus ()); + void visit (HIR::IdentifierPattern &pattern) + { + translated + = ctx->get_backend ()->local_variable (fndecl, pattern.variable_ident, + translated_type, NULL /*decl_var*/, + false /*address_taken*/, locus); } private: CompileVarDecl (Context *ctx, ::Bfunction *fndecl) - : HIRCompileBase (ctx), fndecl (fndecl), translated (nullptr) + : HIRCompileBase (ctx), fndecl (fndecl), translated_type (nullptr), + translated (nullptr) {} ::Bfunction *fndecl; + ::Btype *translated_type; + Location locus; ::Bvariable *translated; }; -- cgit v1.1 From 2b7518cf8ae5e34aec81dbb8efb6ea15bb95c68c Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 16 Jan 2021 16:02:26 +0000 Subject: Add struct_field_expression support This adds in struct field expressions and should be generic enough for tuples later on. --- gcc/rust/backend/rust-compile-expr.h | 25 +++++++++++++++++++++++++ gcc/rust/hir/rust-ast-lower-expr.h | 19 +++++++++++++++++++ gcc/rust/hir/tree/rust-hir-expr.h | 8 ++++++++ gcc/rust/resolve/rust-ast-resolve-expr.h | 5 +++++ gcc/rust/typecheck/rust-hir-type-check-expr.h | 24 ++++++++++++++++++++++++ gcc/rust/typecheck/rust-tyty.h | 11 +++++++++-- 6 files changed, 90 insertions(+), 2 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 682ff79..98e8ee1 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -433,6 +433,31 @@ public: translated = CompileExpr::Compile (expr.get_expr_in_parens ().get (), ctx); } + void visit (HIR::FieldAccessExpr &expr) + { + // resolve the receiver back to ADT type + TyTy::TyBase *receiver = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + expr.get_receiver_expr ()->get_mappings ().get_hirid (), &receiver)) + { + rust_error_at (expr.get_receiver_expr ()->get_locus_slow (), + "unresolved type for receiver"); + return; + } + rust_assert (receiver->get_kind () == TyTy::TypeKind::ADT); + + TyTy::ADTType *adt = (TyTy::ADTType *) receiver; + size_t index = 0; + adt->get_field (expr.get_field_name (), &index); + + Bexpression *struct_ref + = CompileExpr::Compile (expr.get_receiver_expr ().get (), ctx); + + translated + = ctx->get_backend ()->struct_field_expression (struct_ref, index, + expr.get_locus ()); + } + private: CompileExpr (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {} diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index 1003e8c..29be5cc 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -544,6 +544,25 @@ public: std::move (outer_attribs), expr.get_locus ()); } + void visit (AST::FieldAccessExpr &expr) + { + std::vector inner_attribs; + std::vector outer_attribs; + + HIR::Expr *receiver + = ASTLoweringExpr::translate (expr.get_receiver_expr ().get ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + translated + = new HIR::FieldAccessExpr (mapping, + std::unique_ptr (receiver), + expr.get_field_name (), + std::move (outer_attribs), expr.get_locus ()); + } + private: ASTLoweringExpr () : translated (nullptr), translated_array_elems (nullptr), terminated (false) diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index bb8499a..cc717a8 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -2370,6 +2370,14 @@ public: void accept_vis (HIRVisitor &vis) override; + std::unique_ptr &get_receiver_expr () + { + rust_assert (receiver != nullptr); + return receiver; + } + + Identifier get_field_name () const { return field; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 58de087..21b2194 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -187,6 +187,11 @@ public: ResolveExpr::go (expr.get_expr_in_parens ().get (), expr.get_node_id ()); } + void visit (AST::FieldAccessExpr &expr) + { + ResolveExpr::go (expr.get_receiver_expr ().get (), expr.get_node_id ()); + } + private: ResolveExpr (NodeId parent) : ResolverBase (parent) {} }; diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index dd3c8b9..a6cf286 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -440,6 +440,30 @@ public: infered = TypeCheckExpr::Resolve (expr.get_expr_in_parens ().get ()); } + void visit (HIR::FieldAccessExpr &expr) + { + auto struct_base + = TypeCheckExpr::Resolve (expr.get_receiver_expr ().get ()); + if (struct_base->get_kind () != TyTy::TypeKind::ADT) + { + rust_error_at (expr.get_locus (), "expected ADT Type got: [%s]", + struct_base->as_string ().c_str ()); + return; + } + + TyTy::ADTType *adt = (TyTy::ADTType *) struct_base; + auto resolved = adt->get_field (expr.get_field_name ()); + if (resolved == nullptr) + { + rust_error_at (expr.get_locus (), "unknown field [%s] for type [%s]", + expr.get_field_name ().c_str (), + adt->as_string ().c_str ()); + return; + } + + infered = resolved->get_field_type (); + } + private: TypeCheckExpr (bool is_final_expr) : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr), diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 1e529bd..db34f7e 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -194,12 +194,19 @@ public: StructFieldType *get_field (size_t index) { return fields.at (index); } - StructFieldType *get_field (const std::string &lookup) + StructFieldType *get_field (const std::string &lookup, + size_t *index = nullptr) { + size_t i = 0; for (auto &field : fields) { if (field->get_name ().compare (lookup) == 0) - return field; + { + if (index != nullptr) + *index = i; + return field; + } + i++; } return nullptr; } -- cgit v1.1 From c55cd0e10c00d66cf159fc8f3f309186e1a576d1 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Mon, 18 Jan 2021 15:17:50 +0100 Subject: Fix '#include ' GCC doesn't like that: In file included from [...] ./mm_malloc.h:42:12: error: attempt to use poisoned "malloc" return malloc (__size); ^ See commit e7b3f654f2ab0400c95c0517387a9ad645a5c4cd, for example. --- gcc/rust/parse/rust-parse-impl.h | 2 -- gcc/rust/parse/rust-parse.cc | 2 -- gcc/rust/rust-system.h | 2 +- 3 files changed, 1 insertion(+), 5 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index f6bd0f6..7b72bbb 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -22,8 +22,6 @@ along with GCC; see the file COPYING3. If not see #include "rust-diagnostics.h" -#include // for std::find - namespace Rust { // Left binding powers of operations. enum binding_powers diff --git a/gcc/rust/parse/rust-parse.cc b/gcc/rust/parse/rust-parse.cc index 62076ee..fdad97c 100644 --- a/gcc/rust/parse/rust-parse.cc +++ b/gcc/rust/parse/rust-parse.cc @@ -41,8 +41,6 @@ along with GCC; see the file COPYING3. If not see #endif // maybe put these back in if compiling no longer works -#include // for std::find - /* TODO: move non-essential stuff back here from rust-parse-impl.h after * confirming that it works */ diff --git a/gcc/rust/rust-system.h b/gcc/rust/rust-system.h index 26c9b33..d62e676 100644 --- a/gcc/rust/rust-system.h +++ b/gcc/rust/rust-system.h @@ -20,6 +20,7 @@ #ifndef RUST_SYSTEM_H #define RUST_SYSTEM_H +#define INCLUDE_ALGORITHM #include "config.h" /* Define this so that inttypes.h defines the PRI?64 macros even @@ -30,7 +31,6 @@ // These must be included before the #poison declarations in system.h. -#include #include #include #include -- cgit v1.1 From 3713577c36eeba454e8bd3aef6bfce5ee6683c2b Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Mon, 18 Jan 2021 15:34:54 +0100 Subject: Turn brace-enclosed initializer list into actual assignments ... as used otherwise, in this file. And, this avoids: [...]/source-gcc/gcc/rust/parse/rust-parse-impl.h:12243:72: error: could not convert '{false, true}' from '' to 'Rust::ParseRestrictions' = {/* can_be_struct_expr = */ false, /* entered_from_unary = */ true}; ^ --- gcc/rust/parse/rust-parse-impl.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 7b72bbb..ea468ca 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -12239,10 +12239,9 @@ Parser::null_denotation ( // HACK: as struct expressions should always be value expressions, // cannot be referenced - ParseRestrictions entered_from_unary - = {/* can_be_struct_expr = */ false, /* entered_from_unary = */ true}; - /*entered_from_unary.entered_from_unary = true; - entered_from_unary.can_be_struct_expr = false;*/ + ParseRestrictions entered_from_unary; + entered_from_unary.entered_from_unary = true; + entered_from_unary.can_be_struct_expr = false; if (lexer.peek_token ()->get_id () == MUT) { -- cgit v1.1 From 89631998d2ffda0c0c05066c148c6fc19398da5c Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 18 Jan 2021 22:57:46 +0000 Subject: Delcare first case for ADT types field access fail to type resolve. The type resolver must ensure LHS for assignments where the LHS was infered to be ? and the node mappings have a definition ID we know the declaration id and can reassign the TyTy so further references know its type. --- gcc/rust/typecheck/rust-hir-type-check-expr.h | 38 ++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index a6cf286..a49dc70 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -137,9 +137,41 @@ public: auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); infered = lhs->combine (rhs); - // need to overrite the lhs type with this combination - context->insert_type (expr.get_lhs ()->get_mappings ().get_hirid (), - infered); + + // in the case of declare first for an ADT Type: + // + // let a; + // a = Foo{..} + // let b = a.field; + // + // The lhs will have a TyTy of INFER and so when the declaration is + // referenced it will still have an unknown type so we will fail to resolve + // FieldAccessExpr + if (lhs->get_kind () == TyTy::TypeKind::INFER) + { + NodeId ast_node_id = expr.get_lhs ()->get_mappings ().get_nodeid (); + NodeId ref_node_id; + if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + return; + + Definition def; + if (!resolver->lookup_definition (ref_node_id, &def)) + { + rust_error_at (expr.get_locus (), + "assignment infer - unknown reference"); + return; + } + + HirId ref; + if (!mappings->lookup_node_to_hir ( + expr.get_mappings ().get_crate_num (), def.parent, &ref)) + { + rust_error_at (expr.get_locus (), + "assignment infer - reverse lookup failure"); + return; + } + context->insert_type (ref, infered); + } } void visit (HIR::IdentifierExpr &expr) -- cgit v1.1 From 9a942d6fbd0cc087cbc801ce4681a498e59dce2c Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 18 Jan 2021 14:51:36 +0000 Subject: Add in TupleStruct support This adds in tuple struct support with name and type resolution. The arguments and number of arguments are validated against. Test cases added for those errors too. --- gcc/rust/ast/rust-item.h | 25 +++++++-- gcc/rust/backend/rust-compile-expr.h | 19 +------ gcc/rust/backend/rust-compile-item.h | 47 ++++++++--------- gcc/rust/backend/rust-compile-resolve-path.cc | 12 ++--- gcc/rust/backend/rust-compile-resolve-path.h | 2 - gcc/rust/backend/rust-compile.cc | 47 +++++++++++++++++ gcc/rust/hir/rust-ast-lower-item.h | 61 ++++++++++++++++++++- gcc/rust/hir/tree/rust-hir-item.h | 38 ++++++++++---- gcc/rust/resolve/rust-ast-resolve-expr.h | 1 - gcc/rust/resolve/rust-ast-resolve-item.h | 12 ++++- gcc/rust/resolve/rust-ast-resolve-toplevel.h | 7 +++ gcc/rust/typecheck/rust-hir-type-check-expr.h | 23 +++++--- gcc/rust/typecheck/rust-hir-type-check-toplevel.h | 29 +++++++++- gcc/rust/typecheck/rust-hir-type-check-type.h | 2 +- gcc/rust/typecheck/rust-tyty-call.h | 5 +- gcc/rust/typecheck/rust-tyty-rules.h | 5 +- gcc/rust/typecheck/rust-tyty.cc | 64 +++++++++++++++++++++-- gcc/rust/typecheck/rust-tyty.h | 12 +++-- 18 files changed, 322 insertions(+), 89 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 6ebb2e9..a1b505d 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -1817,13 +1817,14 @@ public: Visibility vis, std::vector outer_attrs = std::vector ()) : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)), - field_name (std::move (field_name)), field_type (std::move (field_type)) + field_name (std::move (field_name)), field_type (std::move (field_type)), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} // Copy constructor StructField (StructField const &other) : outer_attrs (other.outer_attrs), visibility (other.visibility), - field_name (other.field_name) + field_name (other.field_name), node_id (other.node_id) { // guard to prevent null dereference if (other.field_type != nullptr) @@ -1838,6 +1839,7 @@ public: field_name = other.field_name; visibility = other.visibility; outer_attrs = other.outer_attrs; + node_id = other.node_id; // guard to prevent null dereference if (other.field_type != nullptr) @@ -1959,6 +1961,7 @@ private: std::unique_ptr field_type; // should this store location info? + NodeId node_id; public: // Returns whether tuple field has outer attributes. @@ -1972,12 +1975,14 @@ public: TupleField (std::unique_ptr field_type, Visibility vis, std::vector outer_attrs = std::vector ()) : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)), - field_type (std::move (field_type)) + field_type (std::move (field_type)), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} // Copy constructor with clone TupleField (TupleField const &other) - : outer_attrs (other.outer_attrs), visibility (other.visibility) + : outer_attrs (other.outer_attrs), visibility (other.visibility), + node_id (other.node_id) { // guard to prevent null dereference (only required if error) if (other.field_type != nullptr) @@ -1991,6 +1996,7 @@ public: { visibility = other.visibility; outer_attrs = other.outer_attrs; + node_id = other.node_id; // guard to prevent null dereference (only required if error) if (other.field_type != nullptr) @@ -2016,6 +2022,8 @@ public: std::string as_string () const; + NodeId get_node_id () const { return node_id; }; + // TODO: this mutable getter seems really dodgy. Think up better way. std::vector &get_outer_attrs () { return outer_attrs; } const std::vector &get_outer_attrs () const { return outer_attrs; } @@ -2053,6 +2061,15 @@ public: std::vector &get_fields () { return fields; } const std::vector &get_fields () const { return fields; } + void iterate (std::function cb) + { + for (auto &field : fields) + { + if (!cb (field)) + return; + } + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 98e8ee1..8b99574 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -86,24 +86,7 @@ public: ctx->add_statement (s); } - void visit (HIR::CallExpr &expr) - { - Bexpression *fn = ResolvePathRef::Compile (expr.get_fnexpr (), ctx); - rust_assert (fn != nullptr); - - std::vector args; - expr.iterate_params ([&] (HIR::Expr *p) mutable -> bool { - Bexpression *compiled_expr = CompileExpr::Compile (p, ctx); - rust_assert (compiled_expr != nullptr); - args.push_back (compiled_expr); - return true; - }); - - auto fncontext = ctx->peek_fn (); - translated - = ctx->get_backend ()->call_expression (fncontext.fndecl, fn, args, - nullptr, expr.get_locus ()); - } + void visit (HIR::CallExpr &expr); void visit (HIR::IdentifierExpr &expr) { diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index a367ac7..c8cffc7 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -37,35 +37,32 @@ public: item->accept_vis (compiler); } - virtual ~CompileItem () {} - - void visit (HIR::StructStruct &struct_decl) + void visit (HIR::TupleStruct &struct_decl) { - std::vector fields; - struct_decl.iterate ([&] (HIR::StructField &field) mutable -> bool { - TyTy::TyBase *resolved_type = nullptr; - bool ok - = ctx->get_tyctx ()->lookup_type (field.get_mappings ().get_hirid (), - &resolved_type); - rust_assert (ok); + TyTy::TyBase *resolved = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + struct_decl.get_mappings ().get_hirid (), &resolved)) + { + rust_fatal_error (struct_decl.get_locus (), + "Failed to lookup type for struct decl"); + return; + } - Btype *compiled_field_ty - = TyTyCompile::compile (ctx->get_backend (), resolved_type); + TyTyResolveCompile::compile (ctx, resolved); + } - Backend::Btyped_identifier f (field.field_name, compiled_field_ty, - field.get_locus ()); - fields.push_back (std::move (f)); - return true; - }); + void visit (HIR::StructStruct &struct_decl) + { + TyTy::TyBase *resolved = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + struct_decl.get_mappings ().get_hirid (), &resolved)) + { + rust_fatal_error (struct_decl.get_locus (), + "Failed to lookup type for struct decl"); + return; + } - Btype *struct_type_record = ctx->get_backend ()->struct_type (fields); - Btype *named_struct - = ctx->get_backend ()->named_type (struct_decl.get_identifier (), - struct_type_record, - struct_decl.get_locus ()); - ctx->push_type (named_struct); - ctx->insert_compiled_type (struct_decl.get_mappings ().get_hirid (), - named_struct); + TyTyResolveCompile::compile (ctx, resolved); } void visit (HIR::StaticItem &var) diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index 374f8a0..37285b7 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -32,7 +32,6 @@ ResolvePathRef::visit (HIR::PathInExpression &expr) if (!ctx->get_resolver ()->lookup_resolved_name ( expr.get_mappings ().get_nodeid (), &ref_node_id)) { - rust_fatal_error (expr.get_locus (), "failed to look up resolved name"); return; } @@ -40,7 +39,7 @@ ResolvePathRef::visit (HIR::PathInExpression &expr) if (!ctx->get_mappings ()->lookup_node_to_hir ( expr.get_mappings ().get_crate_num (), ref_node_id, &ref)) { - rust_fatal_error (expr.get_locus (), "reverse lookup failure"); + rust_error_at (expr.get_locus (), "reverse lookup failure"); return; } @@ -54,14 +53,14 @@ ResolvePathRef::visit (HIR::PathInExpression &expr) expr.get_mappings ().get_crate_num (), ref); if (resolved_item == nullptr) { - rust_fatal_error (expr.get_locus (), "failed to lookup forward decl"); + rust_error_at (expr.get_locus (), "failed to lookup forward decl"); return; } CompileItem::compile (resolved_item, ctx); if (!ctx->lookup_function_decl (ref, &fn)) { - rust_fatal_error (expr.get_locus (), "forward decl was not compiled"); + rust_error_at (expr.get_locus (), "forward decl was not compiled"); return; } } @@ -78,7 +77,6 @@ ResolvePathType::visit (HIR::PathInExpression &expr) if (!ctx->get_resolver ()->lookup_resolved_type ( expr.get_mappings ().get_nodeid (), &ref_node_id)) { - rust_fatal_error (expr.get_locus (), "failed to look up resolved name"); return; } @@ -86,14 +84,14 @@ ResolvePathType::visit (HIR::PathInExpression &expr) if (!ctx->get_mappings ()->lookup_node_to_hir ( expr.get_mappings ().get_crate_num (), ref_node_id, &ref)) { - rust_fatal_error (expr.get_locus (), "reverse lookup failure"); + rust_error_at (expr.get_locus (), "reverse lookup failure"); return; } // assumes paths are functions for now if (!ctx->lookup_compiled_types (ref, &resolved)) { - rust_fatal_error (expr.get_locus (), "forward decl was not compiled"); + rust_error_at (expr.get_locus (), "forward decl was not compiled"); return; } } diff --git a/gcc/rust/backend/rust-compile-resolve-path.h b/gcc/rust/backend/rust-compile-resolve-path.h index a5543d2..2f3cb68 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.h +++ b/gcc/rust/backend/rust-compile-resolve-path.h @@ -32,7 +32,6 @@ public: { ResolvePathRef resolver (ctx); expr->accept_vis (resolver); - rust_assert (resolver.resolved != nullptr); return resolver.resolved; } @@ -51,7 +50,6 @@ public: { ResolvePathType resolver (ctx); expr->accept_vis (resolver); - rust_assert (resolver.resolved != nullptr); return resolver.resolved; } diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 772d975..6519a47 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -48,6 +48,53 @@ CompileCrate::go () CompileItem::compile (item.get (), ctx, true); } +// rust-compile-expr.h + +void +CompileExpr::visit (HIR::CallExpr &expr) +{ + // this can be a function call or it can be a constructor for a tuple struct + Bexpression *fn = ResolvePathRef::Compile (expr.get_fnexpr (), ctx); + if (fn != nullptr) + { + std::vector args; + expr.iterate_params ([&] (HIR::Expr *p) mutable -> bool { + Bexpression *compiled_expr = CompileExpr::Compile (p, ctx); + rust_assert (compiled_expr != nullptr); + args.push_back (compiled_expr); + return true; + }); + + auto fncontext = ctx->peek_fn (); + translated + = ctx->get_backend ()->call_expression (fncontext.fndecl, fn, args, + nullptr, expr.get_locus ()); + } + else + { + Btype *type = ResolvePathType::Compile (expr.get_fnexpr (), ctx); + if (type == nullptr) + { + rust_fatal_error (expr.get_locus (), + "failed to lookup type associated with call"); + return; + } + + // this assumes all fields are in order from type resolution and if a base + // struct was specified those fields are filed via accesors + std::vector vals; + expr.iterate_params ([&] (HIR::Expr *argument) mutable -> bool { + Bexpression *e = CompileExpr::Compile (argument, ctx); + vals.push_back (e); + return true; + }); + + translated + = ctx->get_backend ()->constructor_expression (type, vals, + expr.get_locus ()); + } +} + // rust-compile-block.h void diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index 3cf044e..6122335 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -38,10 +38,67 @@ public: { ASTLoweringItem resolver; item->accept_vis (resolver); + + // this is useful for debugging + // if (resolver.translated == nullptr) + // { + // rust_fatal_error (item->get_locus_slow (), "failed to lower: %s", + // item->as_string ().c_str ()); + // return nullptr; + // } + return resolver.translated; } - virtual ~ASTLoweringItem () {} + void visit (AST::TupleStruct &struct_decl) + { + std::vector > generic_params; + std::vector > where_clause_items; + HIR::WhereClause where_clause (std::move (where_clause_items)); + HIR::Visibility vis = HIR::Visibility::create_public (); + std::vector outer_attrs; + + std::vector fields; + struct_decl.iterate ([&] (AST::TupleField &field) mutable -> bool { + std::vector outer_attrs; + HIR::Visibility vis = HIR::Visibility::create_public (); + HIR::Type *type + = ASTLoweringType::translate (field.get_field_type ().get ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, field.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id ( + crate_num)); + + // FIXME + // AST::TupleField is missing Location info + Location field_locus; + HIR::TupleField translated_field (mapping, + std::unique_ptr (type), vis, + field_locus, outer_attrs); + fields.push_back (std::move (translated_field)); + return true; + }); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, struct_decl.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + + translated = new HIR::TupleStruct (mapping, std::move (fields), + struct_decl.get_identifier (), + std::move (generic_params), + std::move (where_clause), vis, + std::move (outer_attrs), + struct_decl.get_locus ()); + + mappings->insert_defid_mapping (mapping.get_defid (), translated); + mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (), + translated); + mappings->insert_location (crate_num, mapping.get_hirid (), + struct_decl.get_locus ()); + } void visit (AST::StructStruct &struct_decl) { @@ -51,7 +108,7 @@ public: HIR::Visibility vis = HIR::Visibility::create_public (); std::vector outer_attrs; - bool is_unit = false; + bool is_unit = struct_decl.is_unit_struct (); std::vector fields; struct_decl.iterate ([&] (AST::StructField &field) mutable -> bool { std::vector outer_attrs; diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 69e39c8..6a58ca0 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -1604,7 +1604,9 @@ private: std::unique_ptr field_type; - // should this store location info? + Location locus; + + Analysis::NodeMapping mappings; public: // Returns whether tuple field has outer attributes. @@ -1615,16 +1617,18 @@ public: bool has_visibility () const { return !visibility.is_error (); } // Complete constructor - TupleField (std::unique_ptr field_type, Visibility vis, + TupleField (Analysis::NodeMapping mapping, std::unique_ptr field_type, + Visibility vis, Location locus, std::vector outer_attrs = std::vector ()) : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)), - field_type (std::move (field_type)) + field_type (std::move (field_type)), locus (locus), mappings (mapping) {} // Copy constructor with clone TupleField (TupleField const &other) : outer_attrs (other.outer_attrs), visibility (other.visibility), - field_type (other.field_type->clone_type ()) + field_type (other.field_type->clone_type ()), locus (other.locus), + mappings (other.mappings) {} ~TupleField () = default; @@ -1635,6 +1639,8 @@ public: field_type = other.field_type->clone_type (); visibility = other.visibility; outer_attrs = other.outer_attrs; + locus = other.locus; + mappings = other.mappings; return *this; } @@ -1646,13 +1652,13 @@ public: // Returns whether tuple field is in an error state. bool is_error () const { return field_type == nullptr; } - // Creates an error state tuple field. - static TupleField create_error () - { - return TupleField (nullptr, Visibility::create_error ()); - } - std::string as_string () const; + + Analysis::NodeMapping get_mappings () { return mappings; } + + Location get_locus () const { return locus; } + + std::unique_ptr &get_field_type () { return field_type; } }; // Rust tuple declared using struct keyword HIR node @@ -1677,6 +1683,18 @@ public: void accept_vis (HIRVisitor &vis) override; + std::vector &get_fields () { return fields; } + const std::vector &get_fields () const { return fields; } + + void iterate (std::function cb) + { + for (auto &field : fields) + { + if (!cb (field)) + return; + } + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 21b2194..9a7e231 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -83,7 +83,6 @@ public: ResolveExpr::go (p, expr.get_node_id ()); return true; }); - // resolver->insert_resolved_name(NodeId refId,NodeId defId) } void visit (AST::AssignmentExpr &expr) diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index b0b979f..02d6dfa 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -40,10 +40,20 @@ public: ~ResolveItem () {} + void visit (AST::TupleStruct &struct_decl) + { + struct_decl.iterate ([&] (AST::TupleField &field) mutable -> bool { + ResolveType::go (field.get_field_type ().get (), + struct_decl.get_node_id ()); + return true; + }); + } + void visit (AST::StructStruct &struct_decl) { struct_decl.iterate ([&] (AST::StructField &field) mutable -> bool { - ResolveType::go (field.get_field_type ().get (), field.get_node_id ()); + ResolveType::go (field.get_field_type ().get (), + struct_decl.get_node_id ()); return true; }); } diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h index 447fe4b..47435a7 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -36,6 +36,13 @@ public: ~ResolveTopLevel () {} + void visit (AST::TupleStruct &struct_decl) + { + resolver->get_type_scope ().insert (struct_decl.get_identifier (), + struct_decl.get_node_id (), + struct_decl.get_locus ()); + } + void visit (AST::StructStruct &struct_decl) { resolver->get_type_scope ().insert (struct_decl.get_identifier (), diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index a49dc70..5f2477e 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -77,7 +77,7 @@ public: } identifier += ")"; infered = new TyTy::ADTType (expr.get_mappings ().get_hirid (), identifier, - fields); + true, fields); } void visit (HIR::ReturnExpr &expr) @@ -94,14 +94,17 @@ public: auto fn = expr.get_fnexpr (); auto fn_node_id = fn->get_mappings ().get_nodeid (); - // then lookup the reference_node_id + // CallExpr might be a function but it might also be a TupleStruct NodeId ref_node_id; if (!resolver->lookup_resolved_name (fn_node_id, &ref_node_id)) { - rust_error_at (expr.get_locus (), - "Failed to lookup reference for node: %s", - expr.as_string ().c_str ()); - return; + if (!resolver->lookup_resolved_type (fn_node_id, &ref_node_id)) + { + rust_error_at (expr.get_locus (), + "Failed to lookup reference for node: %s", + expr.as_string ().c_str ()); + return; + } } // node back to HIR @@ -109,7 +112,8 @@ public: if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (), ref_node_id, &ref)) { - rust_error_at (expr.get_locus (), "reverse lookup failure"); + rust_error_at (expr.get_locus (), "reverse lookup failure for node %u", + ref_node_id); return; } @@ -125,6 +129,11 @@ public: } infered = TyTy::TypeCheckCallExpr::go (lookup, expr); + if (infered == nullptr) + { + rust_error_at (expr.get_locus (), "failed to lookup type to CallExpr"); + return; + } TyTy::InferType infer (expr.get_mappings ().get_hirid ()); infered = infer.combine (infered); diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index ecee372..55c0d38 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -37,6 +37,32 @@ public: item->accept_vis (resolver); } + void visit (HIR::TupleStruct &struct_decl) + { + std::vector fields; + + size_t idx = 0; + struct_decl.iterate ([&] (HIR::TupleField &field) mutable -> bool { + TyTy::TyBase *field_type + = TypeCheckType::Resolve (field.get_field_type ().get ()); + TyTy::StructFieldType *ty_field + = new TyTy::StructFieldType (field.get_mappings ().get_hirid (), + std::to_string (idx), field_type); + fields.push_back (ty_field); + context->insert_type (field.get_mappings ().get_hirid (), + ty_field->get_field_type ()); + idx++; + return true; + }); + + TyTy::TyBase *type + = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (), + struct_decl.get_identifier (), true, + std::move (fields)); + + context->insert_type (struct_decl.get_mappings ().get_hirid (), type); + } + void visit (HIR::StructStruct &struct_decl) { std::vector fields; @@ -54,7 +80,8 @@ public: TyTy::TyBase *type = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (), - struct_decl.get_identifier (), std::move (fields)); + struct_decl.get_identifier (), false, + std::move (fields)); context->insert_type (struct_decl.get_mappings ().get_hirid (), type); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index 8b9a77c..77dc9c0 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -107,7 +107,7 @@ public: } identifier += ")"; translated = new TyTy::ADTType (tuple.get_mappings ().get_hirid (), - identifier, fields); + identifier, true, fields); } void visit (HIR::TypePath &path) diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h index c3fcb1a..06918c2 100644 --- a/gcc/rust/typecheck/rust-tyty-call.h +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -41,7 +41,6 @@ public: void visit (UnitType &type) override { gcc_unreachable (); } void visit (InferType &type) override { gcc_unreachable (); } void visit (StructFieldType &type) override { gcc_unreachable (); } - void visit (ADTType &type) override { gcc_unreachable (); } void visit (ParamType &type) override { gcc_unreachable (); } void visit (ArrayType &type) override { gcc_unreachable (); } void visit (BoolType &type) override { gcc_unreachable (); } @@ -50,6 +49,10 @@ public: void visit (FloatType &type) override { gcc_unreachable (); } void visit (ErrorType &type) override { gcc_unreachable (); } + // tuple-structs + void visit (ADTType &type) override; + + // call fns void visit (FnType &type) override; private: diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 5353004..0d8d856 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -438,8 +438,9 @@ public: fields.push_back ((TyTy::StructFieldType *) combined); } - resolved = new TyTy::ADTType (type.get_ref (), type.get_ty_ref (), - type.get_name (), fields); + resolved + = new TyTy::ADTType (type.get_ref (), type.get_ty_ref (), + type.get_name (), type.is_tuple_struct (), fields); } private: diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index e007c1f..7ca60c8 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -157,7 +157,8 @@ ADTType::clone () for (auto &f : fields) cloned_fields.push_back ((StructFieldType *) f->clone ()); - return new ADTType (get_ref (), get_ty_ref (), get_name (), cloned_fields); + return new ADTType (get_ref (), get_ty_ref (), get_name (), + is_tuple_struct (), cloned_fields); } void @@ -387,11 +388,62 @@ FloatType::clone () } void +TypeCheckCallExpr::visit (ADTType &type) +{ + if (!type.is_tuple_struct ()) + { + rust_error_at (call.get_locus (), "Expected TupleStruct"); + return; + } + + if (call.num_params () != type.num_fields ()) + { + rust_error_at (call.get_locus (), + "unexpected number of arguments %lu expected %lu", + call.num_params (), type.num_fields ()); + return; + } + + size_t i = 0; + call.iterate_params ([&] (HIR::Expr *p) mutable -> bool { + StructFieldType *field = type.get_field (i); + TyBase *field_tyty = field->get_field_type (); + + TyBase *arg = Resolver::TypeCheckExpr::Resolve (p); + if (arg == nullptr) + { + rust_error_at (p->get_locus_slow (), "failed to resolve argument type"); + return false; + } + + auto res = field_tyty->combine (arg); + if (res == nullptr) + return false; + + delete res; + i++; + return true; + }); + + if (i != call.num_params ()) + { + rust_error_at (call.get_locus (), + "unexpected number of arguments %lu expected %lu", i, + call.num_params ()); + return; + } + + resolved = type.clone (); +} + +void TypeCheckCallExpr::visit (FnType &type) { if (call.num_params () != type.num_params ()) { - rust_error_at (call.get_locus (), "differing number of arguments"); + rust_error_at (call.get_locus (), + "unexpected number of arguments %lu expected %lu", + call.num_params (), type.num_params ()); return; } @@ -409,12 +461,18 @@ TypeCheckCallExpr::visit (FnType &type) if (res == nullptr) return false; + delete res; i++; return true; }); if (i != call.num_params ()) - return; + { + rust_error_at (call.get_locus (), + "unexpected number of arguments %lu expected %lu", i, + call.num_params ()); + return; + } resolved = type.get_return_type (); } diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index db34f7e..b0ccf24 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -169,15 +169,16 @@ private: class ADTType : public TyBase { public: - ADTType (HirId ref, std::string identifier, + ADTType (HirId ref, std::string identifier, bool is_tuple, std::vector fields) - : TyBase (ref, ref, TypeKind::ADT), identifier (identifier), fields (fields) + : TyBase (ref, ref, TypeKind::ADT), identifier (identifier), + is_tuple (is_tuple), fields (fields) {} - ADTType (HirId ref, HirId ty_ref, std::string identifier, + ADTType (HirId ref, HirId ty_ref, std::string identifier, bool is_tuple, std::vector fields) : TyBase (ref, ty_ref, TypeKind::ADT), identifier (identifier), - fields (fields) + is_tuple (is_tuple), fields (fields) {} void accept_vis (TyVisitor &vis) override; @@ -192,6 +193,8 @@ public: std::string get_name () const { return identifier; } + bool is_tuple_struct () const { return is_tuple; } + StructFieldType *get_field (size_t index) { return fields.at (index); } StructFieldType *get_field (const std::string &lookup, @@ -218,6 +221,7 @@ public: private: std::string identifier; + bool is_tuple; std::vector fields; }; -- cgit v1.1 From f8d41b7e8a3a65382dc5ce30dfb3f85abe298d19 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 18 Jan 2021 15:51:35 +0000 Subject: Add TupleIndexExpressions Now we can type resolve and reference the results from TupleIndexExpr's. --- gcc/rust/backend/rust-compile-expr.h | 11 ++++++++ gcc/rust/hir/rust-ast-lower-expr.h | 19 ++++++++++++++ gcc/rust/hir/tree/rust-hir-expr.h | 6 +++++ gcc/rust/resolve/rust-ast-resolve-expr.h | 5 ++++ gcc/rust/typecheck/rust-hir-type-check-expr.h | 36 +++++++++++++++++++++++++++ 5 files changed, 77 insertions(+) (limited to 'gcc/rust') diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 8b99574..ff02d6b 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -38,6 +38,17 @@ public: return compiler.translated; } + void visit (HIR::TupleIndexExpr &expr) + { + HIR::Expr *tuple_expr = expr.get_tuple_expr ().get (); + TupleIndex index = expr.get_tuple_index (); + + Bexpression *receiver_ref = CompileExpr::Compile (tuple_expr, ctx); + translated + = ctx->get_backend ()->struct_field_expression (receiver_ref, index, + expr.get_locus ()); + } + void visit (HIR::TupleExpr &expr) { if (expr.is_unit ()) diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index 29be5cc..6f872ab 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -132,6 +132,25 @@ public: return resolver.translated; } + void visit (AST::TupleIndexExpr &expr) + { + std::vector outer_attribs; + + HIR::Expr *tuple_expr + = ASTLoweringExpr::translate (expr.get_tuple_expr ().get (), &terminated); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated + = new HIR::TupleIndexExpr (mapping, + std::unique_ptr (tuple_expr), + expr.get_tuple_index (), + std::move (outer_attribs), expr.get_locus ()); + } + void visit (AST::TupleExpr &expr) { std::vector inner_attribs; diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index cc717a8..a81d523 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -1314,6 +1314,12 @@ public: void accept_vis (HIRVisitor &vis) override; + std::unique_ptr &get_tuple_expr () + { + rust_assert (tuple_expr != nullptr); + return tuple_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 9a7e231..91ed6e0 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -35,6 +35,11 @@ public: expr->accept_vis (resolver); }; + void visit (AST::TupleIndexExpr &expr) + { + ResolveExpr::go (expr.get_tuple_expr ().get (), expr.get_node_id ()); + } + void visit (AST::TupleExpr &expr) { if (expr.is_unit ()) diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 5f2477e..fddbdeb 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -46,6 +46,42 @@ public: return resolver.infered; } + void visit (HIR::TupleIndexExpr &expr) + { + auto resolved = TypeCheckExpr::Resolve (expr.get_tuple_expr ().get ()); + if (resolved == nullptr) + { + rust_error_at (expr.get_tuple_expr ()->get_locus_slow (), + "failed to resolve TupleIndexExpr receiver"); + return; + } + if (resolved->get_kind () != TyTy::TypeKind::ADT) + { + rust_error_at (expr.get_tuple_expr ()->get_locus_slow (), + "Expected ADT type got: %s", + resolved->as_string ().c_str ()); + return; + } + + TyTy::ADTType *adt = (TyTy::ADTType *) resolved; + TupleIndex index = expr.get_tuple_index (); + if ((size_t) index >= adt->num_fields ()) + { + rust_error_at (expr.get_locus (), "unknown field at index %i", index); + return; + } + + auto field_tyty = adt->get_field ((size_t) index); + if (field_tyty == nullptr) + { + rust_error_at (expr.get_locus (), + "failed to lookup field type at index %i", index); + return; + } + + infered = field_tyty->get_field_type (); + } + void visit (HIR::TupleExpr &expr) { if (expr.is_unit ()) -- cgit v1.1 From 6e2acd529fcfa43368f7ea8209cc5e6b88d2bd79 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 18 Jan 2021 16:47:16 +0000 Subject: Support Struct field index initialisation For TupleStructs the constructor can take field indexes to support change or ordering of the fields. --- gcc/rust/backend/rust-compile-struct-field-expr.h | 2 ++ gcc/rust/backend/rust-compile.cc | 6 ++++++ gcc/rust/hir/rust-ast-lower-struct-field-expr.h | 2 ++ gcc/rust/hir/rust-ast-lower.cc | 16 ++++++++++++++ gcc/rust/hir/tree/rust-hir-expr.h | 2 ++ .../resolve/rust-ast-resolve-struct-expr-field.h | 2 +- gcc/rust/resolve/rust-ast-resolve.cc | 6 ++++++ .../typecheck/rust-hir-type-check-struct-field.h | 2 ++ gcc/rust/typecheck/rust-hir-type-check.cc | 25 ++++++++++++++++++++++ 9 files changed, 62 insertions(+), 1 deletion(-) (limited to 'gcc/rust') diff --git a/gcc/rust/backend/rust-compile-struct-field-expr.h b/gcc/rust/backend/rust-compile-struct-field-expr.h index a394f7a..0e54281 100644 --- a/gcc/rust/backend/rust-compile-struct-field-expr.h +++ b/gcc/rust/backend/rust-compile-struct-field-expr.h @@ -38,6 +38,8 @@ public: void visit (HIR::StructExprFieldIdentifierValue &field); + void visit (HIR::StructExprFieldIndexValue &field); + private: CompileStructExprField (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 6519a47..cb6272f 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -228,5 +228,11 @@ CompileStructExprField::visit (HIR::StructExprFieldIdentifierValue &field) translated = CompileExpr::Compile (field.get_value (), ctx); } +void +CompileStructExprField::visit (HIR::StructExprFieldIndexValue &field) +{ + translated = CompileExpr::Compile (field.get_value (), ctx); +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/hir/rust-ast-lower-struct-field-expr.h b/gcc/rust/hir/rust-ast-lower-struct-field-expr.h index 1b444a5..71c1f1f 100644 --- a/gcc/rust/hir/rust-ast-lower-struct-field-expr.h +++ b/gcc/rust/hir/rust-ast-lower-struct-field-expr.h @@ -46,6 +46,8 @@ public: void visit (AST::StructExprFieldIdentifierValue &field); + void visit (AST::StructExprFieldIndexValue &field); + private: ASTLowerStructExprField () : translated (nullptr) {} diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index 55c6f72..d4c8224 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -212,5 +212,21 @@ ASTLowerStructExprField::visit (AST::StructExprFieldIdentifierValue &field) field.get_locus ()); } +void +ASTLowerStructExprField::visit (AST::StructExprFieldIndexValue &field) +{ + HIR::Expr *value = ASTLoweringExpr::translate (field.get_value ().get ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, field.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated + = new HIR::StructExprFieldIndexValue (mapping, field.get_index (), + std::unique_ptr (value), + field.get_locus ()); +} + } // namespace HIR } // namespace Rust diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index a81d523..a50f744 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -1591,6 +1591,8 @@ public: void accept_vis (HIRVisitor &vis) override; + TupleIndex get_tuple_index () const { return index; }; + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h index c705a03..45d3e59 100644 --- a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h +++ b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h @@ -41,7 +41,7 @@ public: void visit (AST::StructExprFieldIdentifierValue &field); - // TODO + void visit (AST::StructExprFieldIndexValue &field); private: ResolveStructExprField (NodeId parent) : ResolverBase (parent) {} diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index e0b4f3a..910cd86 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -318,5 +318,11 @@ ResolveStructExprField::visit (AST::StructExprFieldIdentifierValue &field) ResolveExpr::go (field.get_value ().get (), field.get_node_id ()); } +void +ResolveStructExprField::visit (AST::StructExprFieldIndexValue &field) +{ + ResolveExpr::go (field.get_value ().get (), field.get_node_id ()); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h index 727569d..02bc9df 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h +++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h @@ -44,6 +44,8 @@ public: void visit (HIR::StructExprFieldIdentifierValue &field); + void visit (HIR::StructExprFieldIndexValue &field); + private: TypeCheckStructExpr () : TypeCheckBase (), resolved (nullptr), struct_path_resolved (nullptr) diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index a5b9b8b..6819627 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -197,5 +197,30 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field) fields_assigned.insert (field.field_name); } +void +TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) +{ + std::string field_name (std::to_string (field.get_tuple_index ())); + auto it = fields_assigned.find (field_name); + if (it != fields_assigned.end ()) + { + rust_fatal_error (field.get_locus (), "used more than once"); + return; + } + + TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value ()); + TyTy::StructFieldType *field_type + = struct_path_resolved->get_field (field_name); + if (field_type == nullptr) + { + rust_error_at (field.get_locus (), "unknown field"); + return; + } + + resolved_field = field_type->get_field_type ()->combine (value); + if (resolved_field != nullptr) + fields_assigned.insert (field_name); +} + } // namespace Resolver } // namespace Rust -- cgit v1.1 From 12f7bd0fc4e9ab4e98869b5265aea6bacfb31d03 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 18 Jan 2021 17:57:22 +0000 Subject: Support struct initializers using Identifiers This resolves each identifier for its respective field. It includes fixes for the TypeResolver to print errors instead of asserts where we loose decent debug info. --- gcc/rust/ast/rust-ast.h | 2 + gcc/rust/ast/rust-expr.h | 2 + gcc/rust/backend/rust-compile-struct-field-expr.h | 2 + gcc/rust/backend/rust-compile.cc | 10 ++++ gcc/rust/hir/rust-ast-lower-struct-field-expr.h | 13 +++-- gcc/rust/hir/rust-ast-lower.cc | 13 +++++ gcc/rust/hir/tree/rust-hir-expr.h | 2 + .../resolve/rust-ast-resolve-struct-expr-field.h | 5 +- gcc/rust/resolve/rust-ast-resolve.cc | 9 +++ .../typecheck/rust-hir-type-check-struct-field.h | 2 + gcc/rust/typecheck/rust-hir-type-check.cc | 29 +++++++++ gcc/rust/typecheck/rust-tyty-resolver.h | 68 ++++++++++++++++------ gcc/rust/util/rust-hir-map.cc | 24 ++++++++ gcc/rust/util/rust-hir-map.h | 6 ++ 14 files changed, 163 insertions(+), 24 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 941b2fe..34122bb 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -882,6 +882,8 @@ public: virtual NodeId get_node_id () const { return node_id; } + virtual void set_node_id (NodeId id) { node_id = id; } + protected: // Constructor Expr (std::vector outer_attribs = std::vector ()) diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 8a1fd6e..6dba7fd 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1604,6 +1604,8 @@ public: void accept_vis (ASTVisitor &vis) override; + Identifier get_field_name () const { return field_name; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/backend/rust-compile-struct-field-expr.h b/gcc/rust/backend/rust-compile-struct-field-expr.h index 0e54281..0a16f6a 100644 --- a/gcc/rust/backend/rust-compile-struct-field-expr.h +++ b/gcc/rust/backend/rust-compile-struct-field-expr.h @@ -40,6 +40,8 @@ public: void visit (HIR::StructExprFieldIndexValue &field); + void visit (HIR::StructExprFieldIdentifier &field); + private: CompileStructExprField (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index cb6272f..ce6d827 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -234,5 +234,15 @@ CompileStructExprField::visit (HIR::StructExprFieldIndexValue &field) translated = CompileExpr::Compile (field.get_value (), ctx); } +void +CompileStructExprField::visit (HIR::StructExprFieldIdentifier &field) +{ + // we can make the field look like an identifier expr to take advantage of + // existing code + HIR::IdentifierExpr expr (field.get_mappings (), field.get_field_name (), + field.get_locus ()); + translated = CompileExpr::Compile (&expr, ctx); +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/hir/rust-ast-lower-struct-field-expr.h b/gcc/rust/hir/rust-ast-lower-struct-field-expr.h index 71c1f1f..c44c9f9 100644 --- a/gcc/rust/hir/rust-ast-lower-struct-field-expr.h +++ b/gcc/rust/hir/rust-ast-lower-struct-field-expr.h @@ -34,10 +34,13 @@ public: field->accept_vis (compiler); rust_assert (compiler.translated != nullptr); - // compiler.mappings->insert_hir_expr ( - // compiler.translated->get_mappings ().get_crate_num (), - // compiler.translated->get_mappings ().get_hirid (), - // compiler.translated); + compiler.mappings->insert_hir_struct_field ( + compiler.translated->get_mappings ().get_crate_num (), + compiler.translated->get_mappings ().get_hirid (), compiler.translated); + compiler.mappings->insert_location ( + compiler.translated->get_mappings ().get_crate_num (), + compiler.translated->get_mappings ().get_hirid (), + field->get_locus_slow ()); return compiler.translated; } @@ -48,6 +51,8 @@ public: void visit (AST::StructExprFieldIndexValue &field); + void visit (AST::StructExprFieldIdentifier &field); + private: ASTLowerStructExprField () : translated (nullptr) {} diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index d4c8224..dac2320 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -228,5 +228,18 @@ ASTLowerStructExprField::visit (AST::StructExprFieldIndexValue &field) field.get_locus ()); } +void +ASTLowerStructExprField::visit (AST::StructExprFieldIdentifier &field) +{ + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, field.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated + = new HIR::StructExprFieldIdentifier (mapping, field.get_field_name (), + field.get_locus ()); +} + } // namespace HIR } // namespace Rust diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index a50f744..ff3fbab 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -1496,6 +1496,8 @@ public: void accept_vis (HIRVisitor &vis) override; + Identifier get_field_name () const { return field_name; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h index 45d3e59..3916473 100644 --- a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h +++ b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h @@ -26,8 +26,7 @@ namespace Rust { namespace Resolver { // this resolves values being assigned not that the field actually exists yet. -// We cant resolve the field to struct until type resolution since the HIR -// Mappings don't exist yet. + class ResolveStructExprField : public ResolverBase { public: @@ -43,6 +42,8 @@ public: void visit (AST::StructExprFieldIndexValue &field); + void visit (AST::StructExprFieldIdentifier &field); + private: ResolveStructExprField (NodeId parent) : ResolverBase (parent) {} }; diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 910cd86..ec53ae0 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -324,5 +324,14 @@ ResolveStructExprField::visit (AST::StructExprFieldIndexValue &field) ResolveExpr::go (field.get_value ().get (), field.get_node_id ()); } +void +ResolveStructExprField::visit (AST::StructExprFieldIdentifier &field) +{ + AST::IdentifierExpr expr (field.get_field_name (), field.get_locus ()); + expr.set_node_id (field.get_node_id ()); + + ResolveExpr::go (&expr, field.get_node_id ()); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h index 02bc9df..48ab40f 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h +++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h @@ -46,6 +46,8 @@ public: void visit (HIR::StructExprFieldIndexValue &field); + void visit (HIR::StructExprFieldIdentifier &field); + private: TypeCheckStructExpr () : TypeCheckBase (), resolved (nullptr), struct_path_resolved (nullptr) diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index 6819627..6f8c3a1 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -222,5 +222,34 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) fields_assigned.insert (field_name); } +void +TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field) +{ + auto it = fields_assigned.find (field.get_field_name ()); + if (it != fields_assigned.end ()) + { + rust_fatal_error (field.get_locus (), "used more than once"); + return; + } + + TyTy::StructFieldType *field_type + = struct_path_resolved->get_field (field.get_field_name ()); + if (field_type == nullptr) + { + rust_error_at (field.get_locus (), "unknown field"); + return; + } + + // we can make the field look like an identifier expr to take advantage of + // existing code to figure out the type + HIR::IdentifierExpr expr (field.get_mappings (), field.get_field_name (), + field.get_locus ()); + TyTy::TyBase *value = TypeCheckExpr::Resolve (&expr); + + resolved_field = field_type->get_field_type ()->combine (value); + if (resolved_field != nullptr) + fields_assigned.insert (field.field_name); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-resolver.h b/gcc/rust/typecheck/rust-tyty-resolver.h index 3c31076..eb03ff9 100644 --- a/gcc/rust/typecheck/rust-tyty-resolver.h +++ b/gcc/rust/typecheck/rust-tyty-resolver.h @@ -44,7 +44,8 @@ public: void go (Rib *rib) { - rib->iterate_decls ([&] (NodeId decl_node_id, Location) mutable -> bool { + rib->iterate_decls ([&] (NodeId decl_node_id, + Location locus) mutable -> bool { // type inference in rust means we need to gather and examine all // references of this decl and combine each to make sure the type is // correctly inferred. Consider the example: @@ -52,33 +53,53 @@ public: // we can only say x is an infer variable then at the assignment // we think x must be an integer + bool ok = true; std::vector gathered_types; rib->iterate_references_for_def ( decl_node_id, [&] (NodeId ref_node) mutable -> bool { HirId hir_node_ref; - bool ok - = mappings->lookup_node_to_hir (mappings->get_current_crate (), - ref_node, &hir_node_ref); - rust_assert (ok); + if (!mappings->lookup_node_to_hir (mappings->get_current_crate (), + ref_node, &hir_node_ref)) + { + rust_error_at (locus, + "failed to reserve lookup HIR node for reference"); + ok = false; + return false; + } TyTy::TyBase *resolved = nullptr; if (!context->lookup_type (hir_node_ref, &resolved)) { // this could be an array/adt type Definition d; - bool ok = resolver->lookup_definition (ref_node, &d); - rust_assert (ok); + if (!resolver->lookup_definition (ref_node, &d)) + { + rust_error_at ( + locus, + "failed to lookup definition for referenced hir node"); + + ok = false; + return false; + } + + if (!mappings->lookup_node_to_hir (mappings->get_current_crate (), + d.parent, &hir_node_ref)) + { + rust_error_at (locus, + "failed to lookup HIR node for parent NodeId"); - ok = mappings->lookup_node_to_hir (mappings->get_current_crate (), - d.parent, &hir_node_ref); - rust_assert (ok); + ok = false; + return false; + } if (!context->lookup_type (hir_node_ref, &resolved)) { - rust_fatal_error ( + rust_error_at ( mappings->lookup_location (hir_node_ref), "failed to lookup type for reference at node [%u]", hir_node_ref); + + ok = false; return false; } } @@ -88,18 +109,29 @@ public: }); Definition d; - bool ok = resolver->lookup_definition (decl_node_id, &d); - rust_assert (ok); + if (!resolver->lookup_definition (decl_node_id, &d)) + { + rust_error_at (locus, "Failed to lookup definition within rib"); + return false; + } HIR::Stmt *decl = nullptr; - ok = mappings->resolve_nodeid_to_stmt (d.parent, &decl); - rust_assert (ok); + if (!mappings->resolve_nodeid_to_stmt (d.parent, &decl)) + { + rust_error_at (locus, "Failed to resolve decl to HIR::Stmt"); + return false; + } TyTy::TyBase *resolved_type = nullptr; - ok = context->lookup_type (decl->get_mappings ().get_hirid (), - &resolved_type); - rust_assert (ok); + if (!context->lookup_type (decl->get_mappings ().get_hirid (), + &resolved_type)) + { + rust_error_at (locus, "Unknown base type for decl in Rib"); + return false; + } + // if it is not infer then it must have been figured out already + // we might need changes for generics later on if (resolved_type->get_kind () != TyTy::TypeKind::INFER) return true; diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index 0fea501..c6e177b 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -350,6 +350,30 @@ Mappings::lookup_hir_param (CrateNum crateNum, HirId id) } void +Mappings::insert_hir_struct_field (CrateNum crateNum, HirId id, + HIR::StructExprField *field) +{ + rust_assert (lookup_hir_stmt (crateNum, id) == nullptr); + + hirStructFieldMappings[crateNum][id] = field; + nodeIdToHirMappings[crateNum][field->get_mappings ().get_nodeid ()] = id; +} + +HIR::StructExprField * +Mappings::lookup_hir_struct_field (CrateNum crateNum, HirId id) +{ + auto it = hirStructFieldMappings.find (crateNum); + if (it == hirStructFieldMappings.end ()) + return nullptr; + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return nullptr; + + return iy->second; +} + +void Mappings::insert_local_defid_mapping (CrateNum crateNum, LocalDefId id, HIR::Item *item) { diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index a400265..3818be9 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -121,6 +121,10 @@ public: void insert_hir_param (CrateNum crateNum, HirId id, HIR::FunctionParam *type); HIR::FunctionParam *lookup_hir_param (CrateNum crateNum, HirId id); + void insert_hir_struct_field (CrateNum crateNum, HirId id, + HIR::StructExprField *type); + HIR::StructExprField *lookup_hir_struct_field (CrateNum crateNum, HirId id); + void walk_local_defids_for_crate (CrateNum crateNum, std::function cb); @@ -159,6 +163,8 @@ private: std::map > hirExprMappings; std::map > hirStmtMappings; std::map > hirParamMappings; + std::map > + hirStructFieldMappings; // location info std::map > locations; -- cgit v1.1 From 4f6f18fe296d4729648eec0b77c8610f0b43445c Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 18 Jan 2021 21:42:53 +0000 Subject: Support struct base reference in constructors This creates implicit FieldAccessExpr or TupleIndexExprs for the missing fields in the constructor using the base struct as the receiver. --- gcc/rust/hir/tree/rust-hir-expr.h | 10 +++ gcc/rust/hir/tree/rust-hir.h | 6 +- gcc/rust/resolve/rust-ast-resolve-expr.h | 8 +++ gcc/rust/typecheck/rust-hir-type-check.cc | 115 +++++++++++++++++++++++++----- gcc/rust/typecheck/rust-tyty.h | 9 +++ 5 files changed, 129 insertions(+), 19 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index ff3fbab..29b5691 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -1669,6 +1669,16 @@ public: } } + std::vector > &get_fields () + { + return fields; + }; + + const std::vector > &get_fields () const + { + return fields; + }; + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h index 5d758ee..fabc31d 100644 --- a/gcc/rust/hir/tree/rust-hir.h +++ b/gcc/rust/hir/tree/rust-hir.h @@ -819,6 +819,9 @@ public: const Analysis::NodeMapping &get_mappings () const { return mappings; } + // Clone function implementation as pure virtual method + virtual Expr *clone_expr_impl () const = 0; + protected: // Constructor Expr (Analysis::NodeMapping mappings, @@ -826,9 +829,6 @@ protected: : outer_attrs (std::move (outer_attribs)), mappings (std::move (mappings)) {} - // Clone function implementation as pure virtual method - virtual Expr *clone_expr_impl () const = 0; - // TODO: think of less hacky way to implement this kind of thing // Sets outer attributes. void set_outer_attrs (std::vector outer_attrs_to_set) diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 91ed6e0..181124a 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -179,6 +179,14 @@ public: { ResolveExpr::go (&struct_expr.get_struct_name (), struct_expr.get_node_id ()); + + if (struct_expr.has_struct_base ()) + { + AST::StructBase &base = struct_expr.get_struct_base (); + ResolveExpr::go (base.get_base_struct ().get (), + struct_expr.get_node_id ()); + } + struct_expr.iterate ( [&] (AST::StructExprField *struct_field) mutable -> bool { ResolveStructExprField::go (struct_field, struct_expr.get_node_id ()); diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index 6f8c3a1..4c09992 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -89,6 +89,22 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) return; } + resolved = struct_path_resolved; + if (struct_expr.has_struct_base ()) + { + TyTy::TyBase *base_resolved + = TypeCheckExpr::Resolve (struct_expr.struct_base->base_struct.get ()); + resolved = struct_path_resolved->combine (base_resolved); + if (resolved == nullptr) + { + rust_fatal_error ( + struct_expr.struct_base->base_struct->get_locus_slow (), + "incompatible types for base struct reference"); + return; + } + } + + bool ok = true; struct_expr.iterate ([&] (HIR::StructExprField *field) mutable -> bool { resolved_field = nullptr; field->accept_vis (*this); @@ -96,6 +112,7 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) { rust_fatal_error (field->get_locus (), "failed to resolve type for field"); + ok = false; return false; } @@ -103,28 +120,94 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) return true; }); - TyTy::TyBase *expr_type = struct_path_resolved; - if (struct_expr.has_struct_base ()) + // something failed setting up the fields + if (!ok) + return; + + // check the arguments are all assigned and fix up the ordering + if (fields_assigned.size () != struct_path_resolved->num_fields ()) { - TyTy::TyBase *base_resolved - = TypeCheckExpr::Resolve (struct_expr.struct_base->base_struct.get ()); - expr_type = expr_type->combine (base_resolved); - if (resolved == nullptr) + if (!struct_expr.has_struct_base ()) { - rust_fatal_error ( - struct_expr.struct_base->base_struct->get_locus_slow (), - "incompatible types for base struct reference"); + rust_error_at (struct_expr.get_locus (), + "constructor is missing fields"); return; } + else + { + // we have a struct base to assign the missing fields from. + // the missing fields can be implicit FieldAccessExprs for the value + std::set missing_fields; + struct_path_resolved->iterate_fields ( + [&] (TyTy::StructFieldType *field) mutable -> bool { + auto it = fields_assigned.find (field->get_name ()); + if (it == fields_assigned.end ()) + missing_fields.insert (field->get_name ()); + return true; + }); + + // we can generate FieldAccessExpr or TupleAccessExpr for the values + // of the missing fields. + for (auto &missing : missing_fields) + { + HIR::Expr *receiver + = struct_expr.struct_base->base_struct->clone_expr_impl (); + + HIR::StructExprField *implicit_field = nullptr; + if (struct_path_resolved->is_tuple_struct ()) + { + std::vector outer_attribs; + TupleIndex tuple_index = std::stoi (missing); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping ( + crate_num, + struct_expr.struct_base->base_struct->get_mappings () + .get_nodeid (), + mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); + + HIR::Expr *field_value = new HIR::TupleIndexExpr ( + mapping, std::unique_ptr (receiver), tuple_index, + std::move (outer_attribs), + struct_expr.struct_base->base_struct->get_locus_slow ()); + + implicit_field = new HIR::StructExprFieldIndexValue ( + mapping, tuple_index, + std::unique_ptr (field_value), + struct_expr.struct_base->base_struct->get_locus_slow ()); + } + else + { + std::vector outer_attribs; + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping ( + crate_num, + struct_expr.struct_base->base_struct->get_mappings () + .get_nodeid (), + mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); + + HIR::Expr *field_value = new HIR::FieldAccessExpr ( + mapping, std::unique_ptr (receiver), missing, + std::move (outer_attribs), + struct_expr.struct_base->base_struct->get_locus_slow ()); + + implicit_field = new HIR::StructExprFieldIdentifierValue ( + mapping, missing, std::unique_ptr (field_value), + struct_expr.struct_base->base_struct->get_locus_slow ()); + } + + struct_expr.get_fields ().push_back ( + std::unique_ptr (implicit_field)); + } + } } - else if (fields_assigned.size () != struct_path_resolved->num_fields ()) - { - rust_fatal_error (struct_expr.get_locus (), - "some fields are not fully assigned"); - return; - } - resolved = expr_type; + // everything is ok, now we need to ensure all field values are ordered + // correctly. The GIMPLE backend uses a simple algorithm that assumes each + // assigned field in the constructor is in the same order as the field in the + // type + + // TODO } void diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index b0ccf24..c32ac02 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -219,6 +219,15 @@ public: std::vector &get_fields () { return fields; } const std::vector &get_fields () const { return fields; } + void iterate_fields (std::function cb) + { + for (auto &f : fields) + { + if (!cb (f)) + return; + } + } + private: std::string identifier; bool is_tuple; -- cgit v1.1 From cb44a8feb815ee31946b33e713c62ac2d333d7be Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 18 Jan 2021 22:21:14 +0000 Subject: When we construct the fields can be in any order. The gimple interface requires us to have the fields in order as to the Algebraic Data Type which it references. --- gcc/rust/hir/tree/rust-hir-expr.h | 11 ++++++ .../typecheck/rust-hir-type-check-struct-field.h | 1 + gcc/rust/typecheck/rust-hir-type-check.cc | 42 ++++++++++++++++++---- 3 files changed, 47 insertions(+), 7 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 29b5691..0b2b542 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -1679,6 +1679,17 @@ public: return fields; }; + std::vector > get_fields_as_owner () + { + return std::move (fields); + }; + + void set_fields_as_owner ( + std::vector > new_fields) + { + fields = std::move (new_fields); + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h index 48ab40f..98db278 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h +++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h @@ -57,6 +57,7 @@ private: TyTy::ADTType *struct_path_resolved; TyTy::TyBase *resolved_field; std::set fields_assigned; + std::map adtFieldIndexToField; }; } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index 4c09992..a33dad1 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -196,6 +196,11 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) struct_expr.struct_base->base_struct->get_locus_slow ()); } + size_t field_index; + bool ok = struct_path_resolved->get_field (missing, &field_index); + rust_assert (ok); + + adtFieldIndexToField[field_index] = implicit_field; struct_expr.get_fields ().push_back ( std::unique_ptr (implicit_field)); } @@ -207,7 +212,18 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) // assigned field in the constructor is in the same order as the field in the // type - // TODO + std::vector > expr_fields + = struct_expr.get_fields_as_owner (); + for (auto &f : expr_fields) + f.release (); + + std::vector > ordered_fields; + for (size_t i = 0; i < adtFieldIndexToField.size (); i++) + { + ordered_fields.push_back ( + std::unique_ptr (adtFieldIndexToField[i])); + } + struct_expr.set_fields_as_owner (std::move (ordered_fields)); } void @@ -266,9 +282,10 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field) return; } + size_t field_index; TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value ()); TyTy::StructFieldType *field_type - = struct_path_resolved->get_field (field.field_name); + = struct_path_resolved->get_field (field.field_name, &field_index); if (field_type == nullptr) { rust_error_at (field.get_locus (), "unknown field"); @@ -277,7 +294,10 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field) resolved_field = field_type->get_field_type ()->combine (value); if (resolved_field != nullptr) - fields_assigned.insert (field.field_name); + { + fields_assigned.insert (field.field_name); + adtFieldIndexToField[field_index] = &field; + } } void @@ -291,9 +311,10 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) return; } + size_t field_index; TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value ()); TyTy::StructFieldType *field_type - = struct_path_resolved->get_field (field_name); + = struct_path_resolved->get_field (field_name, &field_index); if (field_type == nullptr) { rust_error_at (field.get_locus (), "unknown field"); @@ -302,7 +323,10 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) resolved_field = field_type->get_field_type ()->combine (value); if (resolved_field != nullptr) - fields_assigned.insert (field_name); + { + fields_assigned.insert (field_name); + adtFieldIndexToField[field_index] = &field; + } } void @@ -315,8 +339,9 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field) return; } + size_t field_index; TyTy::StructFieldType *field_type - = struct_path_resolved->get_field (field.get_field_name ()); + = struct_path_resolved->get_field (field.get_field_name (), &field_index); if (field_type == nullptr) { rust_error_at (field.get_locus (), "unknown field"); @@ -331,7 +356,10 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field) resolved_field = field_type->get_field_type ()->combine (value); if (resolved_field != nullptr) - fields_assigned.insert (field.field_name); + { + fields_assigned.insert (field.field_name); + adtFieldIndexToField[field_index] = &field; + } } } // namespace Resolver -- cgit v1.1 From f6d33adc6656839aebb4dca02df8efc8be6aedd2 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 19 Jan 2021 12:03:01 +0000 Subject: Fix bug using ADT types as return types to functions When we use anything other than builtin types for returns or parameters the type resolver was missing the NodeId mappings meaning it would alawys fail to resolve them. Then in gimple conversion we need to be able to reference the already created RECORD types instead of always creating new instances. --- gcc/rust/backend/rust-compile-context.h | 80 ++++++++++++++++++++++- gcc/rust/backend/rust-compile-item.h | 15 ++--- gcc/rust/backend/rust-compile-tyty.h | 48 -------------- gcc/rust/hir/rust-ast-lower-item.h | 3 +- gcc/rust/hir/tree/rust-hir-item.h | 2 +- gcc/rust/typecheck/rust-hir-type-check-expr.h | 10 ++- gcc/rust/typecheck/rust-hir-type-check-stmt.h | 10 ++- gcc/rust/typecheck/rust-hir-type-check-toplevel.h | 22 +++---- gcc/rust/typecheck/rust-hir-type-check-type.h | 13 ++-- gcc/rust/typecheck/rust-hir-type-check.cc | 2 +- gcc/rust/typecheck/rust-hir-type-check.h | 2 +- gcc/rust/typecheck/rust-tyctx.cc | 6 +- gcc/rust/typecheck/rust-tyty-resolver.h | 2 +- gcc/rust/util/rust-hir-map.cc | 2 +- 14 files changed, 120 insertions(+), 97 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 5288e51..6516c71 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -225,12 +225,43 @@ public: void visit (TyTy::InferType &type) override { gcc_unreachable (); } - void visit (TyTy::FnType &type) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } void visit (TyTy::ParamType &type) override { gcc_unreachable (); } + void visit (TyTy::FnType &type) override + { + Backend::Btyped_identifier receiver; + std::vector parameters; + std::vector results; + + if (!type.get_return_type ()->is_unit ()) + { + auto hir_type = type.get_return_type (); + auto ret = TyTyResolveCompile::compile (ctx, hir_type); + results.push_back (Backend::Btyped_identifier ( + "_", ret, + ctx->get_mappings ()->lookup_location (hir_type->get_ref ()))); + } + + for (size_t i = 0; i < type.num_params (); i++) + { + auto param_tyty = type.param_at (i); + auto compiled_param_type + = TyTyResolveCompile::compile (ctx, param_tyty->get_base_type ()); + + auto compiled_param = Backend::Btyped_identifier ( + param_tyty->get_identifier (), compiled_param_type, + ctx->get_mappings ()->lookup_location (param_tyty->get_ref ())); + + parameters.push_back (compiled_param); + } + + translated = ctx->get_backend ()->function_type ( + receiver, parameters, results, NULL, + ctx->get_mappings ()->lookup_location (type.get_ref ())); + } + void visit (TyTy::UnitType &type) override { translated = ctx->get_backend ()->void_type (); @@ -320,6 +351,51 @@ private: ::Btype *translated; }; +class TyTyCompileParam : public TyTy::TyVisitor +{ +public: + static ::Bvariable *compile (Context *ctx, Bfunction *fndecl, + TyTy::TyBase *ty) + { + TyTyCompileParam compiler (ctx, fndecl); + ty->accept_vis (compiler); + rust_assert (compiler.translated != nullptr); + return compiler.translated; + } + + ~TyTyCompileParam () {} + + void visit (TyTy::UnitType &type) override { gcc_unreachable (); } + void visit (TyTy::InferType &type) override { gcc_unreachable (); } + void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } + void visit (TyTy::ADTType &type) override { gcc_unreachable (); } + void visit (TyTy::FnType &type) override { gcc_unreachable (); } + void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } + void visit (TyTy::BoolType &type) override { gcc_unreachable (); } + void visit (TyTy::IntType &type) override { gcc_unreachable (); } + void visit (TyTy::UintType &type) override { gcc_unreachable (); } + void visit (TyTy::FloatType &type) override { gcc_unreachable (); } + void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } + + void visit (TyTy::ParamType &type) override + { + auto btype = TyTyResolveCompile::compile (ctx, type.get_base_type ()); + bool tree_addressable = false; + translated = ctx->get_backend ()->parameter_variable ( + fndecl, type.get_identifier (), btype, tree_addressable, + ctx->get_mappings ()->lookup_location (type.get_ref ())); + } + +private: + TyTyCompileParam (Context *ctx, ::Bfunction *fndecl) + : ctx (ctx), fndecl (fndecl), translated (nullptr) + {} + + Context *ctx; + ::Bfunction *fndecl; + ::Bvariable *translated; +}; + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index c8cffc7..82dbc9b 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -127,16 +127,16 @@ public: return; } - TyTy::TyBase *fnType; + TyTy::TyBase *fntype; if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (), - &fnType)) + &fntype)) { rust_fatal_error (function.locus, "failed to lookup function type"); return; } // convert to the actual function type - auto compiled_fn_type = TyTyCompile::compile (ctx->get_backend (), fnType); + ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); unsigned int flags = 0; bool is_main_fn = function.function_name.compare ("main") == 0; @@ -159,15 +159,14 @@ public: ctx->insert_function_decl (function.get_mappings ().get_hirid (), fndecl); // setup the params - TyTy::TyBase *tyret = TyTyExtractRetFromFnType::compile (fnType); + TyTy::TyBase *tyret = TyTyExtractRetFromFnType::compile (fntype); std::vector typarams - = TyTyExtractParamsFromFnType::compile (fnType); + = TyTyExtractParamsFromFnType::compile (fntype); std::vector param_vars; for (auto &it : typarams) { - auto compiled_param - = TyTyCompileParam::compile (ctx->get_backend (), fndecl, it); + auto compiled_param = TyTyCompileParam::compile (ctx, fndecl, it); param_vars.push_back (compiled_param); ctx->insert_var_decl (it->get_ref (), compiled_param); @@ -226,7 +225,7 @@ public: Bvariable *return_address = nullptr; if (function.has_function_return_type ()) { - Btype *return_type = TyTyCompile::compile (ctx->get_backend (), tyret); + Btype *return_type = TyTyResolveCompile::compile (ctx, tyret); bool address_is_taken = false; Bstatement *ret_var_stmt = nullptr; diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index cd220e0..3eb2ca5 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -278,54 +278,6 @@ private: TyTy::TyBase *translated; }; -class TyTyCompileParam : public TyTy::TyVisitor -{ -public: - static ::Bvariable *compile (::Backend *backend, Bfunction *fndecl, - TyTy::TyBase *ty) - { - TyTyCompileParam compiler (backend, fndecl); - ty->accept_vis (compiler); - rust_assert (compiler.translated != nullptr); - return compiler.translated; - } - - ~TyTyCompileParam () {} - - void visit (TyTy::UnitType &type) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } - void visit (TyTy::ADTType &type) override { gcc_unreachable (); } - void visit (TyTy::FnType &type) override { gcc_unreachable (); } - void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } - void visit (TyTy::BoolType &type) override { gcc_unreachable (); } - void visit (TyTy::IntType &type) override { gcc_unreachable (); } - void visit (TyTy::UintType &type) override { gcc_unreachable (); } - void visit (TyTy::FloatType &type) override { gcc_unreachable (); } - void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } - - void visit (TyTy::ParamType &type) override - { - auto btype = TyTyCompile::compile (backend, type.get_base_type ()); - bool tree_addressable = false; - translated = backend->parameter_variable (fndecl, type.get_identifier (), - btype, tree_addressable, - mappings->lookup_location ( - type.get_ref ())); - } - -private: - TyTyCompileParam (::Backend *backend, ::Bfunction *fndecl) - : backend (backend), translated (nullptr), fndecl (fndecl), - mappings (Analysis::Mappings::get ()) - {} - - ::Backend *backend; - ::Bvariable *translated; - ::Bfunction *fndecl; - Analysis::Mappings *mappings; -}; - } // namespace Compile } // namespace Rust diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index 6122335..ec4ef6b 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -274,8 +274,7 @@ public: for (auto ¶m : fn->function_params) { mappings->insert_hir_param (mapping.get_crate_num (), - param.get_mappings ()->get_hirid (), - ¶m); + param.get_mappings ().get_hirid (), ¶m); mappings->insert_location (crate_num, mapping.get_hirid (), param.get_locus ()); } diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 6a58ca0..00608bd 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -448,7 +448,7 @@ public: Type *get_type () { return type.get (); } - Analysis::NodeMapping *get_mappings () { return &mappings; } + Analysis::NodeMapping &get_mappings () { return mappings; } }; // Visibility of item - if the item has it, then it is some form of public diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index fddbdeb..dfa319b 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -41,8 +41,7 @@ public: resolver.infered = new TyTy::UnitType (expr->get_mappings ().get_hirid ()); - resolver.context->insert_type (expr->get_mappings ().get_hirid (), - resolver.infered); + resolver.context->insert_type (expr->get_mappings (), resolver.infered); return resolver.infered; } @@ -215,7 +214,12 @@ public: "assignment infer - reverse lookup failure"); return; } - context->insert_type (ref, infered); + + context->insert_type ( + Analysis::NodeMapping ( + expr.get_lhs ()->get_mappings ().get_crate_num (), ref_node_id, ref, + UNKNOWN_LOCAL_DEFID), + infered); } } diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index bf754db..e60c051 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -69,26 +69,24 @@ public: return; } - context->insert_type (stmt.get_mappings ().get_hirid (), combined); + context->insert_type (stmt.get_mappings (), combined); } else { // let x:i32; if (specified_ty != nullptr) { - context->insert_type (stmt.get_mappings ().get_hirid (), - specified_ty); + context->insert_type (stmt.get_mappings (), specified_ty); } // let x = 123; else if (init_expr_ty != nullptr) { - context->insert_type (stmt.get_mappings ().get_hirid (), - init_expr_ty); + context->insert_type (stmt.get_mappings (), init_expr_ty); } // let x; else { - context->insert_type (stmt.get_mappings ().get_hirid (), + context->insert_type (stmt.get_mappings (), new TyTy::InferType ( stmt.get_mappings ().get_hirid ())); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index 55c0d38..e2bc3ed 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -49,8 +49,7 @@ public: = new TyTy::StructFieldType (field.get_mappings ().get_hirid (), std::to_string (idx), field_type); fields.push_back (ty_field); - context->insert_type (field.get_mappings ().get_hirid (), - ty_field->get_field_type ()); + context->insert_type (field.get_mappings (), ty_field->get_field_type ()); idx++; return true; }); @@ -60,7 +59,7 @@ public: struct_decl.get_identifier (), true, std::move (fields)); - context->insert_type (struct_decl.get_mappings ().get_hirid (), type); + context->insert_type (struct_decl.get_mappings (), type); } void visit (HIR::StructStruct &struct_decl) @@ -73,8 +72,7 @@ public: = new TyTy::StructFieldType (field.get_mappings ().get_hirid (), field.get_field_name (), field_type); fields.push_back (ty_field); - context->insert_type (field.get_mappings ().get_hirid (), - ty_field->get_field_type ()); + context->insert_type (field.get_mappings (), ty_field->get_field_type ()); return true; }); @@ -83,7 +81,7 @@ public: struct_decl.get_identifier (), false, std::move (fields)); - context->insert_type (struct_decl.get_mappings ().get_hirid (), type); + context->insert_type (struct_decl.get_mappings (), type); } void visit (HIR::StaticItem &var) @@ -91,8 +89,7 @@ public: TyTy::TyBase *type = TypeCheckType::Resolve (var.get_type ()); TyTy::TyBase *expr_type = TypeCheckExpr::Resolve (var.get_expr ()); - context->insert_type (var.get_mappings ().get_hirid (), - type->combine (expr_type)); + context->insert_type (var.get_mappings (), type->combine (expr_type)); } void visit (HIR::ConstantItem &constant) @@ -100,8 +97,7 @@ public: TyTy::TyBase *type = TypeCheckType::Resolve (constant.get_type ()); TyTy::TyBase *expr_type = TypeCheckExpr::Resolve (constant.get_expr ()); - context->insert_type (constant.get_mappings ().get_hirid (), - type->combine (expr_type)); + context->insert_type (constant.get_mappings (), type->combine (expr_type)); } void visit (HIR::Function &function) @@ -123,16 +119,16 @@ public: // get the name as well required for later on auto param_type = TypeCheckType::Resolve (param.type.get ()); auto param_tyty - = new TyTy::ParamType (param.get_mappings ()->get_hirid (), + = new TyTy::ParamType (param.get_mappings ().get_hirid (), param.param_name->as_string (), param_type); params.push_back (param_tyty); - context->insert_type (param.get_mappings ()->get_hirid (), param_tyty); + context->insert_type (param.get_mappings (), param_tyty); } auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (), params, ret_type); - context->insert_type (function.get_mappings ().get_hirid (), fnType); + context->insert_type (function.get_mappings (), fnType); } private: diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index 77dc9c0..579dfb0 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -70,7 +70,7 @@ public: type->accept_vis (resolver); if (resolver.translated != nullptr) - resolver.context->insert_type (type->get_mappings ().get_hirid (), + resolver.context->insert_type (type->get_mappings (), resolver.translated); return resolver.translated; @@ -112,10 +112,6 @@ public: void visit (HIR::TypePath &path) { - // check if this is already defined or not - if (context->lookup_type (path.get_mappings ().get_hirid (), &translated)) - return; - // lookup the Node this resolves to NodeId ref; if (!resolver->lookup_resolved_type (path.get_mappings ().get_nodeid (), @@ -132,11 +128,10 @@ public: { // we got an HIR node if (context->lookup_type (hir_lookup, &translated)) - return; + { + return; + } } - - // this might be a struct type (TyTy::ADT) reference - // TODO gcc_unreachable (); } diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index a33dad1..aa3d505 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -116,7 +116,7 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) return false; } - context->insert_type (field->get_mappings ().get_hirid (), resolved_field); + context->insert_type (field->get_mappings (), resolved_field); return true; }); diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index 3572f22..e0458a7 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -37,7 +37,7 @@ public: bool lookup_builtin (std::string name, TyTy::TyBase **type); void insert_builtin (HirId id, NodeId ref, TyTy::TyBase *type); - void insert_type (HirId id, TyTy::TyBase *type); + void insert_type (const Analysis::NodeMapping &mappings, TyTy::TyBase *type); bool lookup_type (HirId id, TyTy::TyBase **type); void insert_type_by_node_id (NodeId ref, HirId id); diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc index 15b4c26..65c5563 100644 --- a/gcc/rust/typecheck/rust-tyctx.cc +++ b/gcc/rust/typecheck/rust-tyctx.cc @@ -73,9 +73,13 @@ TypeCheckContext::insert_builtin (HirId id, NodeId ref, TyTy::TyBase *type) } void -TypeCheckContext::insert_type (HirId id, TyTy::TyBase *type) +TypeCheckContext::insert_type (const Analysis::NodeMapping &mappings, + TyTy::TyBase *type) { rust_assert (type != nullptr); + NodeId ref = mappings.get_nodeid (); + HirId id = mappings.get_hirid (); + node_id_refs[ref] = id; resolved[id] = type; } diff --git a/gcc/rust/typecheck/rust-tyty-resolver.h b/gcc/rust/typecheck/rust-tyty-resolver.h index eb03ff9..a5906d8 100644 --- a/gcc/rust/typecheck/rust-tyty-resolver.h +++ b/gcc/rust/typecheck/rust-tyty-resolver.h @@ -159,7 +159,7 @@ public: } // insert the new resolved definition - context->insert_type (decl->get_mappings ().get_hirid (), resolved_tyty); + context->insert_type (decl->get_mappings (), resolved_tyty); return true; }); } diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index c6e177b..951bdcc 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -332,7 +332,7 @@ Mappings::insert_hir_param (CrateNum crateNum, HirId id, rust_assert (lookup_hir_stmt (crateNum, id) == nullptr); hirParamMappings[crateNum][id] = param; - nodeIdToHirMappings[crateNum][param->get_mappings ()->get_nodeid ()] = id; + nodeIdToHirMappings[crateNum][param->get_mappings ().get_nodeid ()] = id; } HIR::FunctionParam * -- cgit v1.1 From 23edde6fef4321d30f9f2f8c75e6cbfd59b75ca4 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 19 Jan 2021 16:14:12 +0000 Subject: Fixes the ^= and %= compound expression parsing. The input needed to be skipped once the operator was parsed to ensure the lexer did not duplicate the operator. |= still fails but this looks to be a parser problem. --- gcc/rust/lex/rust-lex.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'gcc/rust') diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc index 4606a6c..6dfaea2 100644 --- a/gcc/rust/lex/rust-lex.cc +++ b/gcc/rust/lex/rust-lex.cc @@ -466,7 +466,9 @@ Lexer::build_token () if (peek_input () == '=') { // modulo-assign + skip_input (); current_column += 2; + return Token::make (PERCENT_EQ, loc); } else @@ -479,7 +481,9 @@ Lexer::build_token () if (peek_input () == '=') { // xor-assign? + skip_input (); current_column += 2; + return Token::make (CARET_EQ, loc); } else -- cgit v1.1 From 76b308af7e69f5b50fee96ba4b3584935e621259 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 19 Jan 2021 14:47:01 +0000 Subject: ComparisonExprs and LazyBoolExprs are bools This fixes the expression type resolution to coerce these into bools. For LazyBoolExprs && and || the lhs and rhs are bools. --- gcc/rust/typecheck/rust-hir-type-check-expr.h | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index dfa319b..c47e0ec 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -376,7 +376,12 @@ public: auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); - infered = lhs->combine (rhs); + auto result = lhs->combine (rhs); + if (result == nullptr || result->get_kind () == TyTy::TypeKind::ERROR) + return; + + // we expect this to be + infered = new TyTy::BoolType (expr.get_mappings ().get_hirid ()); } void visit (HIR::LazyBooleanExpr &expr) @@ -384,8 +389,18 @@ public: auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + // we expect the lhs and rhs must be bools at this point + TyTy::BoolType elhs (expr.get_mappings ().get_hirid ()); + lhs = elhs.combine (lhs); + if (lhs == nullptr || lhs->get_kind () == TyTy::TypeKind::ERROR) + return; + + TyTy::BoolType rlhs (expr.get_mappings ().get_hirid ()); + rhs = elhs.combine (rhs); + if (lhs == nullptr || lhs->get_kind () == TyTy::TypeKind::ERROR) + return; + infered = lhs->combine (rhs); - // FIXME this will need to turn into bool } void visit (HIR::IfExpr &expr) -- cgit v1.1 From 6e09093f1f759a78387d214b6d0fe8ba17b752b6 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 19 Jan 2021 17:29:10 +0000 Subject: Enforce the rules for arithmetic operations This adds test cases and enforces the type rules for ArithmeticOrLogical Operators. --- gcc/rust/typecheck/rust-hir-type-check-expr.h | 55 ++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) (limited to 'gcc/rust') diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index c47e0ec..419b911 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -367,8 +367,61 @@ public: { auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + auto combined = lhs->combine (rhs); - infered = lhs->combine (rhs); + // https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators + switch (expr.get_expr_type ()) + { + // integers or floats + case HIR::ArithmeticOrLogicalExpr::ADD: + case HIR::ArithmeticOrLogicalExpr::SUBTRACT: + case HIR::ArithmeticOrLogicalExpr::MULTIPLY: + case HIR::ArithmeticOrLogicalExpr::DIVIDE: + case HIR::ArithmeticOrLogicalExpr::MODULUS: { + bool valid = (combined->get_kind () == TyTy::TypeKind::INT) + || (combined->get_kind () == TyTy::TypeKind::UINT) + || (combined->get_kind () == TyTy::TypeKind::FLOAT); + if (!valid) + { + rust_error_at (expr.get_locus (), "cannot apply operator to %s", + combined->as_string ().c_str ()); + return; + } + } + break; + + // integers or bools + case HIR::ArithmeticOrLogicalExpr::BITWISE_AND: + case HIR::ArithmeticOrLogicalExpr::BITWISE_OR: + case HIR::ArithmeticOrLogicalExpr::BITWISE_XOR: { + bool valid = (combined->get_kind () == TyTy::TypeKind::INT) + || (combined->get_kind () == TyTy::TypeKind::UINT) + || (combined->get_kind () == TyTy::TypeKind::BOOL); + if (!valid) + { + rust_error_at (expr.get_locus (), "cannot apply operator to %s", + combined->as_string ().c_str ()); + return; + } + } + break; + + // integers only + case HIR::ArithmeticOrLogicalExpr::LEFT_SHIFT: + case HIR::ArithmeticOrLogicalExpr::RIGHT_SHIFT: { + bool valid = (combined->get_kind () == TyTy::TypeKind::INT) + || (combined->get_kind () == TyTy::TypeKind::UINT); + if (!valid) + { + rust_error_at (expr.get_locus (), "cannot apply operator to %s", + combined->as_string ().c_str ()); + return; + } + } + break; + } + + infered = combined; } void visit (HIR::ComparisonExpr &expr) -- cgit v1.1 From 85d8754632d597fe3d94404406082bcbb2f5ff94 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 19 Jan 2021 17:02:45 +0000 Subject: Implement NegationExpression This is an example of a unary expression in gimple. The rules for enforcing the types are observed in the type resolver here too. Unary negate cannot be applied to bools but only integers and floats. Unary not cannot be applied to floating points but can be applied to integers and bools. --- gcc/rust/backend/rust-compile-expr.h | 19 +++++++++++++ gcc/rust/hir/rust-ast-lower-expr.h | 28 +++++++++++++++++++ gcc/rust/resolve/rust-ast-resolve-expr.h | 5 ++++ gcc/rust/typecheck/rust-hir-type-check-expr.h | 39 +++++++++++++++++++++++++++ 4 files changed, 91 insertions(+) (limited to 'gcc/rust') diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index ff02d6b..da3c9cd 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -378,6 +378,25 @@ public: expr.get_locus ()); } + void visit (HIR::NegationExpr &expr) + { + Operator op (OPERATOR_INVALID); + switch (expr.get_negation_type ()) + { + case HIR::NegationExpr::NegationType::NEGATE: + op = OPERATOR_MINUS; + break; + + case HIR::NegationExpr::NegationType::NOT: + op = OPERATOR_NOT; + break; + } + + Bexpression *negated_expr = CompileExpr::Compile (expr.get_expr (), ctx); + translated = ctx->get_backend ()->unary_expression (op, negated_expr, + expr.get_locus ()); + } + void visit (HIR::IfExpr &expr) { auto stmt = CompileConditionalBlocks::compile (&expr, ctx); diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index 6f872ab..a924ef2 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -504,6 +504,34 @@ public: expr.get_locus ()); } + void visit (AST::NegationExpr &expr) + { + std::vector outer_attribs; + + HIR::NegationExpr::NegationType type; + switch (expr.get_negation_type ()) + { + case AST::NegationExpr::NegationType::NEGATE: + type = HIR::NegationExpr::NegationType::NEGATE; + break; + case AST::NegationExpr::NegationType::NOT: + type = HIR::NegationExpr::NegationType::NOT; + break; + } + + HIR::Expr *negated_value + = ASTLoweringExpr::translate (expr.get_negated_expr ().get ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + translated + = new HIR::NegationExpr (mapping, + std::unique_ptr (negated_value), type, + std::move (outer_attribs), expr.get_locus ()); + } + void visit (AST::StructExprStructFields &struct_expr) { std::vector inner_attribs; diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 181124a..03b3496 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -128,6 +128,11 @@ public: ResolveExpr::go (expr.get_right_expr ().get (), expr.get_node_id ()); } + void visit (AST::NegationExpr &expr) + { + ResolveExpr::go (expr.get_negated_expr ().get (), expr.get_node_id ()); + } + void visit (AST::IfExpr &expr) { ResolveExpr::go (expr.get_condition_expr ().get (), expr.get_node_id ()); diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 419b911..02830cd 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -456,6 +456,45 @@ public: infered = lhs->combine (rhs); } + void visit (HIR::NegationExpr &expr) + { + auto negated_expr_ty = TypeCheckExpr::Resolve (expr.get_expr ()); + + // https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators + switch (expr.get_negation_type ()) + { + case HIR::NegationExpr::NegationType::NEGATE: { + bool valid + = (negated_expr_ty->get_kind () == TyTy::TypeKind::INT) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::FLOAT); + if (!valid) + { + rust_error_at (expr.get_locus (), "cannot apply unary - to %s", + negated_expr_ty->as_string ().c_str ()); + return; + } + } + break; + + case HIR::NegationExpr::NegationType::NOT: { + bool valid + = (negated_expr_ty->get_kind () == TyTy::TypeKind::BOOL) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::INT) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT); + if (!valid) + { + rust_error_at (expr.get_locus (), "cannot apply unary ! to %s", + negated_expr_ty->as_string ().c_str ()); + return; + } + } + break; + } + + infered = negated_expr_ty; + } + void visit (HIR::IfExpr &expr) { TypeCheckExpr::Resolve (expr.get_if_condition ()); -- cgit v1.1 From e2b761b13e6ccd3a7af4100183bb13e32b5b0da0 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 19 Jan 2021 15:48:51 +0000 Subject: Implement CompoundAssignmentExpressions This expands the AST::CompoundAssignmentExpr into and HIR::AssignmentExpr with the asignee being referenced for lhs and a new artificial HIR::ArithmeticOrLogicalExpression with lhs asignee and rhs the rhs of the original CompoundAssignment expr. --- gcc/rust/hir/rust-ast-lower-expr.h | 58 +++++++++++++++++++++++ gcc/rust/hir/tree/rust-hir-expr.h | 80 -------------------------------- gcc/rust/hir/tree/rust-hir-full-test.cc | 67 -------------------------- gcc/rust/hir/tree/rust-hir-visitor.h | 1 - gcc/rust/resolve/rust-ast-resolve-expr.h | 6 +++ 5 files changed, 64 insertions(+), 148 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index a924ef2..fc18e27 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -532,6 +532,64 @@ public: std::move (outer_attribs), expr.get_locus ()); } + void visit (AST::CompoundAssignmentExpr &expr) + { + HIR::ArithmeticOrLogicalExpr::ExprType kind + = HIR::ArithmeticOrLogicalExpr::ExprType::ADD; + switch (expr.get_expr_type ()) + { + case AST::CompoundAssignmentExpr::ExprType::ADD: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::ADD; + break; + case AST::CompoundAssignmentExpr::ExprType::SUBTRACT: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::SUBTRACT; + break; + case AST::CompoundAssignmentExpr::ExprType::MULTIPLY: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::MULTIPLY; + break; + case AST::CompoundAssignmentExpr::ExprType::DIVIDE: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::DIVIDE; + break; + case AST::CompoundAssignmentExpr::ExprType::MODULUS: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::MODULUS; + break; + case AST::CompoundAssignmentExpr::ExprType::BITWISE_AND: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::BITWISE_AND; + break; + case AST::CompoundAssignmentExpr::ExprType::BITWISE_OR: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::BITWISE_OR; + break; + case AST::CompoundAssignmentExpr::ExprType::BITWISE_XOR: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::BITWISE_XOR; + break; + case AST::CompoundAssignmentExpr::ExprType::LEFT_SHIFT: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::LEFT_SHIFT; + break; + case AST::CompoundAssignmentExpr::ExprType::RIGHT_SHIFT: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::RIGHT_SHIFT; + break; + } + + HIR::Expr *asignee_expr + = ASTLoweringExpr::translate (expr.get_left_expr ().get ()); + HIR::Expr *value + = ASTLoweringExpr::translate (expr.get_right_expr ().get ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + HIR::Expr *operator_expr + = new HIR::ArithmeticOrLogicalExpr (mapping, asignee_expr->clone_expr (), + std::unique_ptr (value), + kind, expr.get_locus ()); + translated + = new HIR::AssignmentExpr (mapping, + std::unique_ptr (asignee_expr), + std::unique_ptr (operator_expr), + expr.get_locus ()); + } + void visit (AST::StructExprStructFields &struct_expr) { std::vector inner_attribs; diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 0b2b542..0ce678b 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -751,86 +751,6 @@ protected: } }; -/* Binary infix compound assignment (arithmetic or logic then assignment) - * expressions. */ -class CompoundAssignmentExpr : public OperatorExpr -{ -public: - enum ExprType - { - ADD, // std::ops::AddAssign - SUBTRACT, // std::ops::SubAssign - MULTIPLY, // std::ops::MulAssign - DIVIDE, // std::ops::DivAssign - MODULUS, // std::ops::RemAssign - BITWISE_AND, // std::ops::BitAndAssign - BITWISE_OR, // std::ops::BitOrAssign - BITWISE_XOR, // std::ops::BitXorAssign - LEFT_SHIFT, // std::ops::ShlAssign - RIGHT_SHIFT // std::ops::ShrAssign - }; - -private: - // Note: overloading trait specified in comments - ExprType expr_type; - std::unique_ptr right_expr; - -public: - std::string as_string () const override; - - ExprType get_expr_type () const { return expr_type; } - - // Use pointers in constructor to enable polymorphism - CompoundAssignmentExpr (Analysis::NodeMapping mappings, - std::unique_ptr value_to_assign_to, - std::unique_ptr value_to_assign, - ExprType expr_kind, Location locus) - : OperatorExpr (std::move (mappings), std::move (value_to_assign_to), - std::vector (), locus), - expr_type (expr_kind), right_expr (std::move (value_to_assign)) - {} - // outer attributes not allowed - - // Have clone in copy constructor - CompoundAssignmentExpr (CompoundAssignmentExpr const &other) - : OperatorExpr (other), expr_type (other.expr_type), - right_expr (other.right_expr->clone_expr ()) - {} - - // Overload assignment operator to clone - CompoundAssignmentExpr &operator= (CompoundAssignmentExpr const &other) - { - OperatorExpr::operator= (other); - // main_or_left_expr = other.main_or_left_expr->clone_expr(); - right_expr = other.right_expr->clone_expr (); - expr_type = other.expr_type; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - CompoundAssignmentExpr (CompoundAssignmentExpr &&other) = default; - CompoundAssignmentExpr &operator= (CompoundAssignmentExpr &&other) = default; - - void accept_vis (HIRVisitor &vis) override; - -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - CompoundAssignmentExpr *clone_expr_impl () const override - { - return new CompoundAssignmentExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - CompoundAssignmentExpr *clone_expr_without_block_impl () const override - { - return new CompoundAssignmentExpr (*this); - } -}; - // Expression in parentheses (i.e. like literally just any 3 + (2 * 6)) class GroupedExpr : public ExprWithoutBlock { diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc index b935376..f4e9f5a 100644 --- a/gcc/rust/hir/tree/rust-hir-full-test.cc +++ b/gcc/rust/hir/tree/rust-hir-full-test.cc @@ -2033,67 +2033,6 @@ ErrorPropagationExpr::as_string () const } std::string -CompoundAssignmentExpr::as_string () const -{ - std::string operator_str; - operator_str.reserve (1); - - // get operator string - switch (expr_type) - { - case ADD: - operator_str = "+"; - break; - case SUBTRACT: - operator_str = "-"; - break; - case MULTIPLY: - operator_str = "*"; - break; - case DIVIDE: - operator_str = "/"; - break; - case MODULUS: - operator_str = "%"; - break; - case BITWISE_AND: - operator_str = "&"; - break; - case BITWISE_OR: - operator_str = "|"; - break; - case BITWISE_XOR: - operator_str = "^"; - break; - case LEFT_SHIFT: - operator_str = "<<"; - break; - case RIGHT_SHIFT: - operator_str = ">>"; - break; - default: - operator_str = "invalid operator. wtf"; - break; - } - - operator_str += "="; - - std::string str ("CompoundAssignmentExpr: "); - if (main_or_left_expr == nullptr || right_expr == nullptr) - { - str += "error. this is probably a parsing failure."; - } - else - { - str += "\n left: " + main_or_left_expr->as_string (); - str += "\n right: " + right_expr->as_string (); - str += "\n operator: " + operator_str; - } - - return str; -} - -std::string ArithmeticOrLogicalExpr::as_string () const { std::string operator_str; @@ -5241,12 +5180,6 @@ AssignmentExpr::accept_vis (HIRVisitor &vis) } void -CompoundAssignmentExpr::accept_vis (HIRVisitor &vis) -{ - vis.visit (*this); -} - -void GroupedExpr::accept_vis (HIRVisitor &vis) { vis.visit (*this); diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h index abb84f5..7fefb69 100644 --- a/gcc/rust/hir/tree/rust-hir-visitor.h +++ b/gcc/rust/hir/tree/rust-hir-visitor.h @@ -77,7 +77,6 @@ public: virtual void visit (LazyBooleanExpr &expr) = 0; virtual void visit (TypeCastExpr &expr) = 0; virtual void visit (AssignmentExpr &expr) = 0; - virtual void visit (CompoundAssignmentExpr &expr) = 0; virtual void visit (GroupedExpr &expr) = 0; // virtual void visit(ArrayElems& elems) = 0; virtual void visit (ArrayElemsValues &elems) = 0; diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 03b3496..229b26a 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -116,6 +116,12 @@ public: ResolveExpr::go (expr.get_right_expr ().get (), expr.get_node_id ()); } + void visit (AST::CompoundAssignmentExpr &expr) + { + ResolveExpr::go (expr.get_left_expr ().get (), expr.get_node_id ()); + ResolveExpr::go (expr.get_right_expr ().get (), expr.get_node_id ()); + } + void visit (AST::ComparisonExpr &expr) { ResolveExpr::go (expr.get_left_expr ().get (), expr.get_node_id ()); -- cgit v1.1 From 9e733f4de4908026a47a62307a9e9a3bf06ce1b1 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 20 Jan 2021 10:31:22 +0000 Subject: Fix usage of parameters and the type resolver Parameter types can be resolved to their base type in combination rules. --- gcc/rust/typecheck/rust-tyty-rules.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 0d8d856..1eaf3e9 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -70,11 +70,7 @@ public: virtual void visit (ParamType &type) override { - Location ref_locus = mappings->lookup_location (type.get_ref ()); - Location def_locus = mappings->lookup_location (base->get_ref ()); - rust_error_at (ref_locus, "expected [%s] got [%s]", - base->as_string ().c_str (), type.as_string ().c_str ()); - rust_error_at (def_locus, "declared here"); + type.get_base_type ()->accept_vis (*this); } virtual void visit (ArrayType &type) override -- cgit v1.1 From be371b9f49e0c4fd7752cad6708fed8b1f2719a3 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 21 Jan 2021 14:02:16 +0000 Subject: Add backend support to create immutable types GCC uses qualified types to create const immutability. --- gcc/rust/rust-backend.h | 3 +++ gcc/rust/rust-gcc.cc | 14 ++++++++++++++ 2 files changed, 17 insertions(+) (limited to 'gcc/rust') diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index 02c12ee..184f8fa 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -112,6 +112,9 @@ public: // Get a pointer type. virtual Btype *pointer_type (Btype *to_type) = 0; + // make type immutable + virtual Btype *immutable_type (Btype *base) = 0; + // Get a function type. The receiver, parameter, and results are // generated from the types in the Function_type. The Function_type // is provided so that the names are available. This should return diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 748aa5a..6f8dc46 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -173,6 +173,8 @@ public: Btype *pointer_type (Btype *); + Btype *immutable_type (Btype *); + Btype *function_type (const Btyped_identifier &, const std::vector &, const std::vector &, Btype *, @@ -848,6 +850,18 @@ Gcc_backend::pointer_type (Btype *to_type) return this->make_type (type); } +// Get immutable type + +Btype * +Gcc_backend::immutable_type (Btype *base) +{ + tree type_tree = base->get_tree (); + if (type_tree == error_mark_node) + return this->error_type (); + tree constified = build_qualified_type (type_tree, TYPE_QUAL_CONST); + return this->make_type (constified); +} + // Make a function type. Btype * -- cgit v1.1 From 5294dfe7dce7a58fbaf2131c7589d115008ebf0e Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 21 Jan 2021 17:04:14 +0000 Subject: Remove TyTy::ParamType this was wrongly used to represent FunctionParams TyTy::ParamType is meant to be used to represent Generic Types which is not handled yet as part of this current milestone. --- gcc/rust/backend/rust-compile-context.h | 56 ++------------ gcc/rust/backend/rust-compile-item.h | 39 +++++++--- gcc/rust/backend/rust-compile-tyty.h | 93 ++--------------------- gcc/rust/hir/tree/rust-hir-item.h | 2 +- gcc/rust/typecheck/rust-hir-type-check-item.h | 1 - gcc/rust/typecheck/rust-hir-type-check-toplevel.h | 11 ++- gcc/rust/typecheck/rust-tyty-call.h | 1 - gcc/rust/typecheck/rust-tyty-resolver.h | 1 - gcc/rust/typecheck/rust-tyty-rules.h | 22 ------ gcc/rust/typecheck/rust-tyty-visitor.h | 1 - gcc/rust/typecheck/rust-tyty.cc | 38 ++------- gcc/rust/typecheck/rust-tyty.h | 50 ++++-------- 12 files changed, 72 insertions(+), 243 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 6516c71..df29e36 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -26,6 +26,7 @@ #include "rust-backend.h" #include "rust-compile-tyty.h" #include "rust-ast-full.h" +#include "rust-hir-full.h" namespace Rust { namespace Compile { @@ -227,8 +228,6 @@ public: void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } - void visit (TyTy::ParamType &type) override { gcc_unreachable (); } - void visit (TyTy::FnType &type) override { Backend::Btyped_identifier receiver; @@ -244,14 +243,14 @@ public: ctx->get_mappings ()->lookup_location (hir_type->get_ref ()))); } - for (size_t i = 0; i < type.num_params (); i++) + for (auto ¶m_pair : type.get_params ()) { - auto param_tyty = type.param_at (i); + auto param_tyty = param_pair.second; auto compiled_param_type - = TyTyResolveCompile::compile (ctx, param_tyty->get_base_type ()); + = TyTyResolveCompile::compile (ctx, param_tyty); auto compiled_param = Backend::Btyped_identifier ( - param_tyty->get_identifier (), compiled_param_type, + param_pair.first->as_string (), compiled_param_type, ctx->get_mappings ()->lookup_location (param_tyty->get_ref ())); parameters.push_back (compiled_param); @@ -351,51 +350,6 @@ private: ::Btype *translated; }; -class TyTyCompileParam : public TyTy::TyVisitor -{ -public: - static ::Bvariable *compile (Context *ctx, Bfunction *fndecl, - TyTy::TyBase *ty) - { - TyTyCompileParam compiler (ctx, fndecl); - ty->accept_vis (compiler); - rust_assert (compiler.translated != nullptr); - return compiler.translated; - } - - ~TyTyCompileParam () {} - - void visit (TyTy::UnitType &type) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } - void visit (TyTy::ADTType &type) override { gcc_unreachable (); } - void visit (TyTy::FnType &type) override { gcc_unreachable (); } - void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } - void visit (TyTy::BoolType &type) override { gcc_unreachable (); } - void visit (TyTy::IntType &type) override { gcc_unreachable (); } - void visit (TyTy::UintType &type) override { gcc_unreachable (); } - void visit (TyTy::FloatType &type) override { gcc_unreachable (); } - void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } - - void visit (TyTy::ParamType &type) override - { - auto btype = TyTyResolveCompile::compile (ctx, type.get_base_type ()); - bool tree_addressable = false; - translated = ctx->get_backend ()->parameter_variable ( - fndecl, type.get_identifier (), btype, tree_addressable, - ctx->get_mappings ()->lookup_location (type.get_ref ())); - } - -private: - TyTyCompileParam (Context *ctx, ::Bfunction *fndecl) - : ctx (ctx), fndecl (fndecl), translated (nullptr) - {} - - Context *ctx; - ::Bfunction *fndecl; - ::Bvariable *translated; -}; - } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index 82dbc9b..bf899d8 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -127,14 +127,21 @@ public: return; } - TyTy::TyBase *fntype; + TyTy::TyBase *fntype_tyty; if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (), - &fntype)) + &fntype_tyty)) { rust_fatal_error (function.locus, "failed to lookup function type"); return; } + if (fntype_tyty->get_kind () != TyTy::TypeKind::FNDEF) + { + rust_error_at (function.get_locus (), "invalid TyTy for function item"); + return; + } + + TyTy::FnType *fntype = (TyTy::FnType *) fntype_tyty; // convert to the actual function type ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); @@ -159,17 +166,31 @@ public: ctx->insert_function_decl (function.get_mappings ().get_hirid (), fndecl); // setup the params - TyTy::TyBase *tyret = TyTyExtractRetFromFnType::compile (fntype); - std::vector typarams - = TyTyExtractParamsFromFnType::compile (fntype); + + TyTy::TyBase *tyret = fntype->return_type (); std::vector param_vars; - for (auto &it : typarams) + size_t i = 0; + for (auto &it : fntype->get_params ()) { - auto compiled_param = TyTyCompileParam::compile (ctx, fndecl, it); - param_vars.push_back (compiled_param); + HIR::FunctionParam &referenced_param = function.function_params.at (i); + auto param_pattern = it.first; + auto param_tyty = it.second; + + auto compiled_param_type + = TyTyResolveCompile::compile (ctx, param_tyty); + + bool tree_addressable = false; + auto compiled_param_var = ctx->get_backend ()->parameter_variable ( + fndecl, param_pattern->as_string (), compiled_param_type, + tree_addressable, + ctx->get_mappings ()->lookup_location (param_tyty->get_ref ())); + + param_vars.push_back (compiled_param_var); - ctx->insert_var_decl (it->get_ref (), compiled_param); + ctx->insert_var_decl (referenced_param.get_mappings ().get_hirid (), + compiled_param_var); + i++; } if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars)) diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index 3eb2ca5..f74b4ac 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -26,6 +26,7 @@ #include "rust-tyty.h" #include "rust-tyty-visitor.h" #include "rust-hir-map.h" +#include "rust-hir-full.h" namespace Rust { namespace Compile { @@ -49,8 +50,6 @@ public: void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } - void visit (TyTy::ParamType &type) override { gcc_unreachable (); } - void visit (TyTy::ADTType &type) override { gcc_unreachable (); } void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } @@ -74,13 +73,14 @@ public: "_", ret, mappings->lookup_location (hir_type->get_ref ()))); } - for (size_t i = 0; i < type.num_params (); i++) + for (auto ¶ms : type.get_params ()) { - auto param_tyty = type.param_at (i); - auto compiled_param_type - = TyTyCompile::compile (backend, param_tyty->get_base_type ()); + auto param_pattern = params.first; + auto param_tyty = params.second; + auto compiled_param_type = TyTyCompile::compile (backend, param_tyty); + auto compiled_param = Backend::Btyped_identifier ( - param_tyty->get_identifier (), compiled_param_type, + param_pattern->as_string (), compiled_param_type, mappings->lookup_location (param_tyty->get_ref ())); parameters.push_back (compiled_param); @@ -199,85 +199,6 @@ private: Analysis::Mappings *mappings; }; -class TyTyExtractParamsFromFnType : public TyTy::TyVisitor -{ -public: - static std::vector compile (TyTy::TyBase *ty) - { - TyTyExtractParamsFromFnType compiler; - ty->accept_vis (compiler); - rust_assert (compiler.ok); - return compiler.translated; - } - - ~TyTyExtractParamsFromFnType () {} - - void visit (TyTy::UnitType &type) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } - void visit (TyTy::ADTType &type) override { gcc_unreachable (); } - void visit (TyTy::ParamType &type) override { gcc_unreachable (); } - void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } - void visit (TyTy::BoolType &type) override { gcc_unreachable (); } - void visit (TyTy::IntType &type) override { gcc_unreachable (); } - void visit (TyTy::UintType &type) override { gcc_unreachable (); } - void visit (TyTy::FloatType &type) override { gcc_unreachable (); } - void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } - - void visit (TyTy::FnType &type) override - { - ok = true; - for (size_t i = 0; i < type.num_params (); i++) - { - translated.push_back (type.param_at (i)); - } - } - -private: - TyTyExtractParamsFromFnType () : ok (false) {} - - bool ok; - std::vector translated; -}; - -class TyTyExtractRetFromFnType : public TyTy::TyVisitor -{ -public: - static TyTy::TyBase *compile (TyTy::TyBase *ty) - { - TyTyExtractRetFromFnType compiler; - ty->accept_vis (compiler); - rust_assert (compiler.ok); - return compiler.translated; - } - - ~TyTyExtractRetFromFnType () {} - - void visit (TyTy::UnitType &type) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } - void visit (TyTy::ADTType &type) override { gcc_unreachable (); } - void visit (TyTy::ParamType &type) override { gcc_unreachable (); } - void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } - void visit (TyTy::BoolType &type) override { gcc_unreachable (); } - void visit (TyTy::IntType &type) override { gcc_unreachable (); } - void visit (TyTy::UintType &type) override { gcc_unreachable (); } - void visit (TyTy::FloatType &type) override { gcc_unreachable (); } - void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } - - void visit (TyTy::FnType &type) override - { - ok = true; - translated = type.get_return_type (); - } - -private: - TyTyExtractRetFromFnType () : ok (false), translated (nullptr) {} - - bool ok; - TyTy::TyBase *translated; -}; - } // namespace Compile } // namespace Rust diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 00608bd..e99dd38 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -404,13 +404,13 @@ public: // A function parameter struct FunctionParam { -public: std::unique_ptr param_name; std::unique_ptr type; Location locus; Analysis::NodeMapping mappings; +public: FunctionParam (Analysis::NodeMapping mappings, std::unique_ptr param_name, std::unique_ptr param_type, Location locus) diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index 20f5adb..566d43e 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -47,7 +47,6 @@ public: void visit (TyTy::InferType &type) override { gcc_unreachable (); } void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } void visit (TyTy::ADTType &type) override { gcc_unreachable (); } - void visit (TyTy::ParamType &type) override { gcc_unreachable (); } void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } void visit (TyTy::BoolType &type) override { gcc_unreachable (); } void visit (TyTy::IntType &type) override { gcc_unreachable (); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index e2bc3ed..fcaf724 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -113,15 +113,14 @@ public: ret_type->set_ref (function.return_type->get_mappings ().get_hirid ()); } - std::vector params; + std::vector > params; for (auto ¶m : function.function_params) { // get the name as well required for later on - auto param_type = TypeCheckType::Resolve (param.type.get ()); - auto param_tyty - = new TyTy::ParamType (param.get_mappings ().get_hirid (), - param.param_name->as_string (), param_type); - params.push_back (param_tyty); + auto param_tyty = TypeCheckType::Resolve (param.get_type ()); + params.push_back ( + std::pair (param.get_param_name (), + param_tyty)); context->insert_type (param.get_mappings (), param_tyty); } diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h index 06918c2..2e98cbb 100644 --- a/gcc/rust/typecheck/rust-tyty-call.h +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -41,7 +41,6 @@ public: void visit (UnitType &type) override { gcc_unreachable (); } void visit (InferType &type) override { gcc_unreachable (); } void visit (StructFieldType &type) override { gcc_unreachable (); } - void visit (ParamType &type) override { gcc_unreachable (); } void visit (ArrayType &type) override { gcc_unreachable (); } void visit (BoolType &type) override { gcc_unreachable (); } void visit (IntType &type) override { gcc_unreachable (); } diff --git a/gcc/rust/typecheck/rust-tyty-resolver.h b/gcc/rust/typecheck/rust-tyty-resolver.h index a5906d8..d48952c 100644 --- a/gcc/rust/typecheck/rust-tyty-resolver.h +++ b/gcc/rust/typecheck/rust-tyty-resolver.h @@ -193,7 +193,6 @@ public: void visit (TyTy::InferType &type) override { gcc_unreachable (); } void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } void visit (TyTy::ADTType &type) override { gcc_unreachable (); } - void visit (TyTy::ParamType &type) override { gcc_unreachable (); } void visit (TyTy::FnType &type) override { gcc_unreachable (); } void visit (TyTy::BoolType &type) override { gcc_unreachable (); } void visit (TyTy::IntType &type) override { gcc_unreachable (); } diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 1eaf3e9..241b9be 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -68,11 +68,6 @@ public: rust_error_at (def_locus, "declared here"); } - virtual void visit (ParamType &type) override - { - type.get_base_type ()->accept_vis (*this); - } - virtual void visit (ArrayType &type) override { Location ref_locus = mappings->lookup_location (type.get_ref ()); @@ -172,8 +167,6 @@ public: void visit (FloatType &type) override { resolved = type.clone (); } - void visit (ParamType &type) override { resolved = type.clone (); } - void visit (ArrayType &type) override { resolved = type.clone (); } void visit (ADTType &type) override { resolved = type.clone (); } @@ -243,21 +236,6 @@ private: FnType *base; }; -class ParamRules : protected BaseRules -{ -public: - ParamRules (ParamType *base) : BaseRules (base), base (base) {} - - TyBase *combine (TyBase *other) - { - // we only case about the base type of a param - return base->get_base_type ()->combine (other); - } - -private: - ParamType *base; -}; - class ArrayRules : protected BaseRules { public: diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h index def43cd..b6759dd 100644 --- a/gcc/rust/typecheck/rust-tyty-visitor.h +++ b/gcc/rust/typecheck/rust-tyty-visitor.h @@ -32,7 +32,6 @@ public: virtual void visit (StructFieldType &type) = 0; virtual void visit (ADTType &type) = 0; virtual void visit (FnType &type) = 0; - virtual void visit (ParamType &type) = 0; virtual void visit (ArrayType &type) = 0; virtual void visit (BoolType &type) = 0; virtual void visit (IntType &type) = 0; diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 7ca60c8..2e09de6 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -173,7 +173,9 @@ FnType::as_string () const std::string params_str = ""; for (auto ¶m : params) { - params_str += param->as_string (); + auto pattern = param.first; + auto ty = param.second; + params_str += pattern->as_string () + " " + ty->as_string (); params_str += ","; } @@ -191,41 +193,16 @@ FnType::combine (TyBase *other) TyBase * FnType::clone () { - std::vector cloned_params; + std::vector > cloned_params; for (auto &p : params) - cloned_params.push_back ((ParamType *) p->clone ()); + cloned_params.push_back ( + std::pair (p.first, p.second->clone ())); return new FnType (get_ref (), get_ty_ref (), cloned_params, get_return_type ()->clone ()); } void -ParamType::accept_vis (TyVisitor &vis) -{ - vis.visit (*this); -} - -std::string -ParamType::as_string () const -{ - return "(" + identifier + " :" + type->as_string () + ")"; -} - -TyBase * -ParamType::combine (TyBase *other) -{ - ParamRules r (this); - return r.combine (other); -} - -TyBase * -ParamType::clone () -{ - return new ParamType (get_ref (), get_ty_ref (), get_identifier (), - get_base_type ()->clone ()); -} - -void ArrayType::accept_vis (TyVisitor &vis) { vis.visit (*this); @@ -449,7 +426,7 @@ TypeCheckCallExpr::visit (FnType &type) size_t i = 0; call.iterate_params ([&] (HIR::Expr *p) mutable -> bool { - TyBase *pt = type.param_at (i); + auto fnparam = type.param_at (i); auto t = Resolver::TypeCheckExpr::Resolve (p); if (t == nullptr) { @@ -457,6 +434,7 @@ TypeCheckCallExpr::visit (FnType &type) return false; } + auto pt = fnparam.second; auto res = pt->combine (t); if (res == nullptr) return false; diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index c32ac02..a73a344 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -234,43 +234,17 @@ private: std::vector fields; }; -class ParamType : public TyBase -{ -public: - ParamType (HirId ref, std::string identifier, TyBase *type) - : TyBase (ref, ref, TypeKind::PARAM), identifier (identifier), type (type) - {} - - ParamType (HirId ref, HirId ty_ref, std::string identifier, TyBase *type) - : TyBase (ref, ty_ref, TypeKind::PARAM), identifier (identifier), - type (type) - {} - - void accept_vis (TyVisitor &vis) override; - - std::string as_string () const override; - - TyBase *combine (TyBase *other) override; - - std::string get_identifier () const { return identifier; } - - TyBase *get_base_type () { return type; } - - TyBase *clone () final override; - -private: - std::string identifier; - TyBase *type; -}; - class FnType : public TyBase { public: - FnType (HirId ref, std::vector params, TyBase *type) - : TyBase (ref, ref, TypeKind::FNDEF), params (params), type (type) + FnType (HirId ref, std::vector > params, + TyBase *type) + : TyBase (ref, ref, TypeKind::FNDEF), params (std::move (params)), + type (type) {} - FnType (HirId ref, HirId ty_ref, std::vector params, + FnType (HirId ref, HirId ty_ref, + std::vector > params, TyBase *type) : TyBase (ref, ty_ref, TypeKind::FNDEF), params (params), type (type) {} @@ -285,14 +259,22 @@ public: size_t num_params () const { return params.size (); } - ParamType *param_at (size_t idx) { return params[idx]; } + std::vector > &get_params () + { + return params; + } + + std::pair ¶m_at (size_t idx) + { + return params[idx]; + } TyBase *get_return_type () { return type; } TyBase *clone () final override; private: - std::vector params; + std::vector > params; TyBase *type; }; -- cgit v1.1 From 0817c29a423aca1c4c3f9ba812f67df35f36fc65 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 21 Jan 2021 17:31:21 +0000 Subject: Add Integer and Float InterenceVariable In order to properly handle all integer types and infer we must follow HM algorithm. This means when we unify every type in the resolver this should keep a chain of HirId of references such that when/if the type is resolved it lookup tables can be updated for the Backend to compile to Gimple. Consider the case: fn test(x:u32) -> u32 {...} let a = test(1); The VarDecl here will have the type let a: = test(1). Since this integer combines with the parameter x:u32 the type resolver knows at this point these must be a u32. let a; a = 1; let b:u32 = a; This is more subtle let a: a: = 1 let b:u32 = a; Since the integer inference variable combines with u32 all previous references can be updated to u32 at this point. In the basic case of: let a; a = 1; This resolves down to: let a:; a = 1 It is not until we complete type-inference we can iterate all the resolved types and HirIds and default any to i32 and any to f32. Any remaining general inference variable are errors. --- gcc/rust/backend/rust-compile-context.h | 31 ++ gcc/rust/backend/rust-compile-expr.h | 8 +- gcc/rust/backend/rust-compile-tyty.h | 2 + gcc/rust/hir/tree/rust-hir-expr.h | 6 +- gcc/rust/hir/tree/rust-hir-full-test.cc | 18 +- gcc/rust/hir/tree/rust-hir.h | 7 +- gcc/rust/rust-session-manager.cc | 5 + gcc/rust/typecheck/rust-hir-type-check-expr.h | 249 ++++++++++----- gcc/rust/typecheck/rust-hir-type-check-item.h | 62 ++-- gcc/rust/typecheck/rust-hir-type-check-stmt.h | 22 +- gcc/rust/typecheck/rust-hir-type-check-toplevel.h | 16 +- gcc/rust/typecheck/rust-hir-type-check-type.h | 32 +- gcc/rust/typecheck/rust-hir-type-check.cc | 134 +++++--- gcc/rust/typecheck/rust-hir-type-check.h | 9 + gcc/rust/typecheck/rust-tycheck-dump.h | 178 +++++++++++ gcc/rust/typecheck/rust-tyty-call.h | 14 +- gcc/rust/typecheck/rust-tyty-resolver.h | 214 ------------- gcc/rust/typecheck/rust-tyty-rules.h | 372 ++++++++++++++++------ gcc/rust/typecheck/rust-tyty-visitor.h | 1 + gcc/rust/typecheck/rust-tyty.cc | 126 ++++++-- gcc/rust/typecheck/rust-tyty.h | 183 ++++++++--- gcc/rust/util/rust-hir-map.cc | 1 + gcc/rust/util/rust-hir-map.h | 8 + 23 files changed, 1085 insertions(+), 613 deletions(-) create mode 100644 gcc/rust/typecheck/rust-tycheck-dump.h delete mode 100644 gcc/rust/typecheck/rust-tyty-resolver.h (limited to 'gcc/rust') diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index df29e36..ed03f02 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -298,6 +298,37 @@ public: translated = named_struct; } + void visit (TyTy::TupleType &type) override + { + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &translated); + if (ok) + return; + + // create implicit struct + std::vector fields; + for (size_t i = 0; i < type.num_fields (); i++) + { + TyTy::TyBase *field = type.get_field (i); + Btype *compiled_field_ty + = TyTyCompile::compile (ctx->get_backend (), field); + + Backend::Btyped_identifier f (std::to_string (i), compiled_field_ty, + ctx->get_mappings ()->lookup_location ( + type.get_ty_ref ())); + fields.push_back (std::move (f)); + } + + Btype *struct_type_record = ctx->get_backend ()->struct_type (fields); + Btype *named_struct + = ctx->get_backend ()->named_type (type.as_string (), struct_type_record, + ctx->get_mappings ()->lookup_location ( + type.get_ty_ref ())); + + ctx->push_type (named_struct); + ctx->insert_compiled_type (type.get_ty_ref (), named_struct); + translated = named_struct; + } + void visit (TyTy::ArrayType &type) override { mpz_t ival; diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index da3c9cd..7c2f32d 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -145,17 +145,19 @@ public: void visit (HIR::LiteralExpr &expr) { + auto literal_value = expr.get_literal (); switch (expr.get_lit_type ()) { case HIR::Literal::BOOL: { - bool bval = expr.as_string ().compare ("true") == 0; + bool bval = literal_value->as_string ().compare ("true") == 0; translated = ctx->get_backend ()->boolean_constant_expression (bval); } return; case HIR::Literal::INT: { mpz_t ival; - if (mpz_init_set_str (ival, expr.as_string ().c_str (), 10) != 0) + if (mpz_init_set_str (ival, literal_value->as_string ().c_str (), 10) + != 0) { rust_fatal_error (expr.get_locus (), "bad number in literal"); return; @@ -178,7 +180,7 @@ public: case HIR::Literal::FLOAT: { mpfr_t fval; - if (mpfr_init_set_str (fval, expr.as_string ().c_str (), 10, + if (mpfr_init_set_str (fval, literal_value->as_string ().c_str (), 10, MPFR_RNDN) != 0) { diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index f74b4ac..b6794bc 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -52,6 +52,8 @@ public: void visit (TyTy::ADTType &type) override { gcc_unreachable (); } + void visit (TyTy::TupleType &type) override { gcc_unreachable (); } + void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } void visit (TyTy::UnitType &type) override diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 0ce678b..69b680d 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -61,7 +61,11 @@ class LiteralExpr : public ExprWithoutBlock Location locus; public: - std::string as_string () const override { return literal.as_string (); } + std::string as_string () const override + { + return "( " + literal.as_string () + " (" + get_mappings ().as_string () + + "))"; + } Literal::LitType get_lit_type () const { return literal.get_lit_type (); } diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc index f4e9f5a..b727917 100644 --- a/gcc/rust/hir/tree/rust-hir-full-test.cc +++ b/gcc/rust/hir/tree/rust-hir-full-test.cc @@ -2072,23 +2072,15 @@ ArithmeticOrLogicalExpr::as_string () const operator_str = ">>"; break; default: - operator_str = "invalid operator. wtf"; + gcc_unreachable (); break; } - std::string str ("ArithmeticOrLogicalExpr: "); - if (main_or_left_expr == nullptr || right_expr == nullptr) - { - str += "error. this is probably a parsing failure."; - } - else - { - str += main_or_left_expr->as_string () + " "; - str += operator_str + " "; - str += right_expr->as_string (); - } + std::string str = main_or_left_expr->as_string () + " "; + str += operator_str + " "; + str += right_expr->as_string (); - return str + "::" + get_mappings ().as_string (); + return "( " + str + " (" + get_mappings ().as_string () + "))"; } std::string diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h index fabc31d..e4a81c5 100644 --- a/gcc/rust/hir/tree/rust-hir.h +++ b/gcc/rust/hir/tree/rust-hir.h @@ -895,7 +895,10 @@ public: ident (std::move (ident)), locus (locus) {} - std::string as_string () const override { return ident; } + std::string as_string () const override + { + return "( " + ident + " (" + get_mappings ().as_string () + "))"; + } Location get_locus () const { return locus; } Location get_locus_slow () const override { return get_locus (); } @@ -908,6 +911,8 @@ public: return std::unique_ptr (clone_identifier_expr_impl ()); } + Identifier get_identifier () const { return ident; } + protected: // Clone method implementation IdentifierExpr *clone_expr_without_block_impl () const override diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index c1df913..281049d 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -34,6 +34,7 @@ #include "rust-ast-resolve.h" #include "rust-ast-lower.h" #include "rust-hir-type-check.h" +#include "rust-tycheck-dump.h" #include "rust-compile.h" extern Linemap * @@ -548,6 +549,10 @@ Session::parse_file (const char *filename) // type resolve type_resolution (hir); + // FIXME this needs an option of itself + // auto buf = Resolver::TypeResolverDump::go (hir); + // fprintf (stderr, "%s\n", buf.c_str ()); + if (saw_errors ()) return; diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 02830cd..8f60f72 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -23,7 +23,6 @@ #include "rust-hir-full.h" #include "rust-tyty.h" #include "rust-tyty-call.h" -#include "rust-tyty-resolver.h" #include "rust-hir-type-check-struct-field.h" namespace Rust { @@ -38,10 +37,15 @@ public: expr->accept_vis (resolver); if (resolver.infered == nullptr) - resolver.infered - = new TyTy::UnitType (expr->get_mappings ().get_hirid ()); + { + resolver.infered + = new TyTy::UnitType (expr->get_mappings ().get_hirid ()); + } + auto ref = expr->get_mappings ().get_hirid (); + resolver.infered->set_ref (ref); resolver.context->insert_type (expr->get_mappings (), resolver.infered); + return resolver.infered; } @@ -54,14 +58,40 @@ public: "failed to resolve TupleIndexExpr receiver"); return; } - if (resolved->get_kind () != TyTy::TypeKind::ADT) + + bool is_valid_type = resolved->get_kind () == TyTy::TypeKind::ADT + || resolved->get_kind () == TyTy::TypeKind::TUPLE; + if (!is_valid_type) { rust_error_at (expr.get_tuple_expr ()->get_locus_slow (), - "Expected ADT type got: %s", + "Expected Tuple or ADT got: %s", resolved->as_string ().c_str ()); return; } + if (resolved->get_kind () == TyTy::TypeKind::TUPLE) + { + TyTy::TupleType *tuple = (TyTy::TupleType *) resolved; + TupleIndex index = expr.get_tuple_index (); + if ((size_t) index >= tuple->num_fields ()) + { + rust_error_at (expr.get_locus (), "unknown field at index %i", + index); + return; + } + + auto field_tyty = tuple->get_field ((size_t) index); + if (field_tyty == nullptr) + { + rust_error_at (expr.get_locus (), + "failed to lookup field type at index %i", index); + return; + } + + infered = field_tyty; + return; + } + TyTy::ADTType *adt = (TyTy::ADTType *) resolved; TupleIndex index = expr.get_tuple_index (); if ((size_t) index >= adt->num_fields ()) @@ -94,34 +124,32 @@ public: return; } - size_t index = 0; - std::string identifier = "("; - std::vector fields; + std::vector fields; for (auto &elem : expr.get_tuple_elems ()) { auto field_ty = TypeCheckExpr::Resolve (elem.get ()); - identifier += field_ty->as_string (); - if ((index + 1) < expr.get_tuple_elems ().size ()) - identifier += ","; - - auto field_tyty - = new TyTy::StructFieldType (elem->get_mappings ().get_hirid (), - std::to_string (index), field_ty); - fields.push_back (field_tyty); - index++; - } - identifier += ")"; - infered = new TyTy::ADTType (expr.get_mappings ().get_hirid (), identifier, - true, fields); + fields.push_back (field_ty->get_ref ()); + } + infered = new TyTy::TupleType (expr.get_mappings ().get_hirid (), fields); } void visit (HIR::ReturnExpr &expr) { - auto ret = context->peek_return_type (); - rust_assert (ret != nullptr); + auto fn_return_tyty = context->peek_return_type (); + rust_assert (fn_return_tyty != nullptr); auto expr_ty = TypeCheckExpr::Resolve (expr.get_expr ()); - infered = ret->combine (expr_ty); + if (expr_ty == nullptr) + { + rust_error_at (expr.get_locus (), + "failed to resolve type for ReturnExpr"); + return; + } + + infered = fn_return_tyty->combine (expr_ty); + fn_return_tyty->append_reference (expr_ty->get_ref ()); + for (auto &ref : infered->get_combined_refs ()) + fn_return_tyty->append_reference (ref); } void visit (HIR::CallExpr &expr) @@ -163,15 +191,13 @@ public: return; } - infered = TyTy::TypeCheckCallExpr::go (lookup, expr); + infered = TyTy::TypeCheckCallExpr::go (lookup, expr, context); if (infered == nullptr) { rust_error_at (expr.get_locus (), "failed to lookup type to CallExpr"); return; } - TyTy::InferType infer (expr.get_mappings ().get_hirid ()); - infered = infer.combine (infered); infered->set_ref (expr.get_mappings ().get_hirid ()); } @@ -181,6 +207,12 @@ public: auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); infered = lhs->combine (rhs); + if (infered == nullptr) + { + rust_error_at (expr.get_locus (), + "failure in TypeInference AssignmentExpr"); + return; + } // in the case of declare first for an ADT Type: // @@ -191,36 +223,34 @@ public: // The lhs will have a TyTy of INFER and so when the declaration is // referenced it will still have an unknown type so we will fail to resolve // FieldAccessExpr - if (lhs->get_kind () == TyTy::TypeKind::INFER) - { - NodeId ast_node_id = expr.get_lhs ()->get_mappings ().get_nodeid (); - NodeId ref_node_id; - if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) - return; - Definition def; - if (!resolver->lookup_definition (ref_node_id, &def)) - { - rust_error_at (expr.get_locus (), - "assignment infer - unknown reference"); - return; - } + NodeId ast_node_id = expr.get_lhs ()->get_mappings ().get_nodeid (); + NodeId ref_node_id; + if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + return; - HirId ref; - if (!mappings->lookup_node_to_hir ( - expr.get_mappings ().get_crate_num (), def.parent, &ref)) - { - rust_error_at (expr.get_locus (), - "assignment infer - reverse lookup failure"); - return; - } + Definition def; + if (!resolver->lookup_definition (ref_node_id, &def)) + { + rust_error_at (expr.get_locus (), + "assignment infer - unknown reference"); + return; + } - context->insert_type ( - Analysis::NodeMapping ( - expr.get_lhs ()->get_mappings ().get_crate_num (), ref_node_id, ref, - UNKNOWN_LOCAL_DEFID), - infered); + HirId ref; + if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (), + def.parent, &ref)) + { + rust_error_at (expr.get_locus (), + "assignment infer - reverse lookup failure"); + return; } + + // FIXME free the old one + context->insert_type ( + Analysis::NodeMapping (expr.get_lhs ()->get_mappings ().get_crate_num (), + ref_node_id, ref, UNKNOWN_LOCAL_DEFID), + infered->clone ()); } void visit (HIR::IdentifierExpr &expr) @@ -265,8 +295,8 @@ public: return; } - TyTy::InferType infer (expr.get_mappings ().get_hirid ()); - infered = infer.combine (lookup); + lookup->append_reference (lookup->get_ref ()); + infered = lookup->clone (); infered->set_ref (expr.get_mappings ().get_hirid ()); } @@ -321,7 +351,10 @@ public: break; default: - ok = context->lookup_builtin ("i32", &infered); + ok = true; + infered = new TyTy::InferType ( + expr.get_mappings ().get_hirid (), + TyTy::InferType::InferTypeKind::INTEGRAL); break; } rust_assert (ok); @@ -339,8 +372,12 @@ public: case CORETYPE_F64: ok = context->lookup_builtin ("f64", &infered); break; + default: - ok = context->lookup_builtin ("f32", &infered); + ok = true; + infered + = new TyTy::InferType (expr.get_mappings ().get_hirid (), + TyTy::InferType::InferTypeKind::FLOAT); break; } rust_assert (ok); @@ -358,9 +395,7 @@ public: break; } - TyTy::InferType infer (expr.get_mappings ().get_hirid ()); - infered = infer.combine (infered); - infered->set_ref (expr.get_mappings ().get_hirid ()); + infered = infered->clone (); } void visit (HIR::ArithmeticOrLogicalExpr &expr) @@ -380,7 +415,13 @@ public: case HIR::ArithmeticOrLogicalExpr::MODULUS: { bool valid = (combined->get_kind () == TyTy::TypeKind::INT) || (combined->get_kind () == TyTy::TypeKind::UINT) - || (combined->get_kind () == TyTy::TypeKind::FLOAT); + || (combined->get_kind () == TyTy::TypeKind::FLOAT) + || (combined->get_kind () == TyTy::TypeKind::INFER + && (((TyTy::InferType *) combined)->get_infer_kind () + == TyTy::InferType::INTEGRAL)) + || (combined->get_kind () == TyTy::TypeKind::INFER + && (((TyTy::InferType *) combined)->get_infer_kind () + == TyTy::InferType::FLOAT)); if (!valid) { rust_error_at (expr.get_locus (), "cannot apply operator to %s", @@ -396,7 +437,10 @@ public: case HIR::ArithmeticOrLogicalExpr::BITWISE_XOR: { bool valid = (combined->get_kind () == TyTy::TypeKind::INT) || (combined->get_kind () == TyTy::TypeKind::UINT) - || (combined->get_kind () == TyTy::TypeKind::BOOL); + || (combined->get_kind () == TyTy::TypeKind::BOOL) + || (combined->get_kind () == TyTy::TypeKind::INFER + && (((TyTy::InferType *) combined)->get_infer_kind () + == TyTy::InferType::INTEGRAL)); if (!valid) { rust_error_at (expr.get_locus (), "cannot apply operator to %s", @@ -410,7 +454,10 @@ public: case HIR::ArithmeticOrLogicalExpr::LEFT_SHIFT: case HIR::ArithmeticOrLogicalExpr::RIGHT_SHIFT: { bool valid = (combined->get_kind () == TyTy::TypeKind::INT) - || (combined->get_kind () == TyTy::TypeKind::UINT); + || (combined->get_kind () == TyTy::TypeKind::UINT) + || (combined->get_kind () == TyTy::TypeKind::INFER + && (((TyTy::InferType *) combined)->get_infer_kind () + == TyTy::InferType::INTEGRAL)); if (!valid) { rust_error_at (expr.get_locus (), "cannot apply operator to %s", @@ -422,6 +469,8 @@ public: } infered = combined; + infered->append_reference (lhs->get_ref ()); + infered->append_reference (rhs->get_ref ()); } void visit (HIR::ComparisonExpr &expr) @@ -435,6 +484,8 @@ public: // we expect this to be infered = new TyTy::BoolType (expr.get_mappings ().get_hirid ()); + infered->append_reference (lhs->get_ref ()); + infered->append_reference (rhs->get_ref ()); } void visit (HIR::LazyBooleanExpr &expr) @@ -454,6 +505,8 @@ public: return; infered = lhs->combine (rhs); + infered->append_reference (lhs->get_ref ()); + infered->append_reference (rhs->get_ref ()); } void visit (HIR::NegationExpr &expr) @@ -467,7 +520,13 @@ public: bool valid = (negated_expr_ty->get_kind () == TyTy::TypeKind::INT) || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT) - || (negated_expr_ty->get_kind () == TyTy::TypeKind::FLOAT); + || (negated_expr_ty->get_kind () == TyTy::TypeKind::FLOAT) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER + && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind () + == TyTy::InferType::INTEGRAL)) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER + && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind () + == TyTy::InferType::FLOAT)); if (!valid) { rust_error_at (expr.get_locus (), "cannot apply unary - to %s", @@ -481,7 +540,10 @@ public: bool valid = (negated_expr_ty->get_kind () == TyTy::TypeKind::BOOL) || (negated_expr_ty->get_kind () == TyTy::TypeKind::INT) - || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT); + || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER + && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind () + == TyTy::InferType::INTEGRAL)); if (!valid) { rust_error_at (expr.get_locus (), "cannot apply unary ! to %s", @@ -492,7 +554,8 @@ public: break; } - infered = negated_expr_ty; + infered = negated_expr_ty->clone (); + infered->append_reference (negated_expr_ty->get_ref ()); } void visit (HIR::IfExpr &expr) @@ -567,23 +630,45 @@ public: void visit (HIR::ArrayIndexExpr &expr) { - // FIXME this should be size type - TyTy::IntType size_ty (expr.get_index_expr ()->get_mappings ().get_hirid (), - TyTy::IntType::I32); - auto resolved - = size_ty.combine (TypeCheckExpr::Resolve (expr.get_index_expr ())); - rust_assert (resolved != nullptr); + TyTy::TyBase *size_ty; + if (!context->lookup_builtin ("i32", &size_ty)) + { + rust_error_at ( + expr.get_locus (), + "Failure looking up size type for index in ArrayIndexExpr"); + return; + } + + auto resolved_index_expr + = size_ty->combine (TypeCheckExpr::Resolve (expr.get_index_expr ())); + if (resolved_index_expr == nullptr) + { + rust_error_at (expr.get_index_expr ()->get_locus_slow (), + "Type Resolver failure in Index for ArrayIndexExpr"); + return; + } + context->insert_type (expr.get_index_expr ()->get_mappings (), + resolved_index_expr); + // resolve the array reference expr.get_array_expr ()->accept_vis (*this); - if (infered->get_kind () != TyTy::TypeKind::ARRAY) + if (infered == nullptr) { - rust_fatal_error (expr.get_array_expr ()->get_locus_slow (), - "expected an ArrayType for index expression"); + rust_error_at (expr.get_index_expr ()->get_locus_slow (), + "failed to resolve array reference expression"); + return; + } + else if (infered->get_kind () != TyTy::TypeKind::ARRAY) + { + rust_error_at (expr.get_index_expr ()->get_locus_slow (), + "expected an ArrayType got [%s]", + infered->as_string ().c_str ()); + infered = nullptr; return; } - // extract the element type out now from the base type - infered = TyTyExtractorArray::ExtractElementTypeFromArray (infered); + TyTy::ArrayType *array_type = (TyTy::ArrayType *) infered; + infered = array_type->get_type ()->clone (); } void visit (HIR::ArrayExpr &expr) @@ -611,6 +696,9 @@ public: { infered_array_elems = infered_array_elems->combine (types.at (i)); } + + for (auto &elem : types) + infered_array_elems->append_reference (elem->get_ref ()); } void visit (HIR::ArrayElemsCopied &elems) @@ -632,9 +720,12 @@ public: { auto struct_base = TypeCheckExpr::Resolve (expr.get_receiver_expr ().get ()); - if (struct_base->get_kind () != TyTy::TypeKind::ADT) + + bool is_valid_type = struct_base->get_kind () == TyTy::TypeKind::ADT; + if (!is_valid_type) { - rust_error_at (expr.get_locus (), "expected ADT Type got: [%s]", + rust_error_at (expr.get_locus (), + "expected ADT or Tuple Type got: [%s]", struct_base->as_string ().c_str ()); return; } diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index 566d43e..d7f9af1 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -24,43 +24,10 @@ #include "rust-hir-type-check-type.h" #include "rust-hir-type-check-stmt.h" #include "rust-tyty-visitor.h" -#include "rust-tyty-resolver.h" namespace Rust { namespace Resolver { -class ResolveFnType : public TyTy::TyVisitor -{ -public: - ResolveFnType (TyTy::TyBase *base) : base (base), state (nullptr) {} - - TyTy::TyBase *go () - { - base->accept_vis (*this); - if (state == nullptr) - gcc_unreachable (); - - return state; - } - - void visit (TyTy::UnitType &type) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } - void visit (TyTy::ADTType &type) override { gcc_unreachable (); } - void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } - void visit (TyTy::BoolType &type) override { gcc_unreachable (); } - void visit (TyTy::IntType &type) override { gcc_unreachable (); } - void visit (TyTy::UintType &type) override { gcc_unreachable (); } - void visit (TyTy::FloatType &type) override { gcc_unreachable (); } - void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } - - void visit (TyTy::FnType &type) override { state = type.return_type (); } - -private: - TyTy::TyBase *base; - TyTy::TyBase *state; -}; - class TypeCheckItem : public TypeCheckBase { public: @@ -72,23 +39,42 @@ public: void visit (HIR::Function &function) { - TyTy::TyBase *fnType; - if (!context->lookup_type (function.get_mappings ().get_hirid (), &fnType)) + TyTy::TyBase *lookup; + if (!context->lookup_type (function.get_mappings ().get_hirid (), &lookup)) { rust_error_at (function.locus, "failed to lookup function type"); return; } + if (lookup->get_kind () != TyTy::TypeKind::FNDEF) + { + rust_error_at (function.get_locus (), + "found invalid type for function [%s]", + lookup->as_string ().c_str ()); + return; + } + // need to get the return type from this - ResolveFnType resolve_fn_type (fnType); - context->push_return_type (resolve_fn_type.go ()); + TyTy::FnType *resolve_fn_type = (TyTy::FnType *) lookup; + auto expected_ret_tyty = resolve_fn_type->return_type (); + context->push_return_type (expected_ret_tyty); TypeCheckExpr::Resolve (function.function_body.get ()); if (function.function_body->has_expr ()) { auto resolved = TypeCheckExpr::Resolve (function.function_body->expr.get ()); - context->peek_return_type ()->combine (resolved); + + auto ret_resolved = expected_ret_tyty->combine (resolved); + if (ret_resolved == nullptr) + { + rust_error_at (function.function_body->expr->get_locus_slow (), + "failed to resolve final expression"); + return; + } + + context->peek_return_type ()->append_reference ( + ret_resolved->get_ref ()); } context->pop_return_type (); diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index e60c051..99be0b7 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -49,10 +49,19 @@ public: void visit (HIR::LetStmt &stmt) { + infered = new TyTy::UnitType (stmt.get_mappings ().get_hirid ()); + TyTy::TyBase *init_expr_ty = nullptr; if (stmt.has_init_expr ()) - init_expr_ty - = TypeCheckExpr::Resolve (stmt.get_init_expr (), is_final_stmt); + { + init_expr_ty + = TypeCheckExpr::Resolve (stmt.get_init_expr (), is_final_stmt); + + init_expr_ty = init_expr_ty->clone (); + auto ref = init_expr_ty->get_ref (); + init_expr_ty->set_ref (stmt.get_mappings ().get_hirid ()); + init_expr_ty->append_reference (ref); + } TyTy::TyBase *specified_ty = nullptr; if (stmt.has_type ()) @@ -86,16 +95,17 @@ public: // let x; else { - context->insert_type (stmt.get_mappings (), - new TyTy::InferType ( - stmt.get_mappings ().get_hirid ())); + context->insert_type ( + stmt.get_mappings (), + new TyTy::InferType (stmt.get_mappings ().get_hirid (), + TyTy::InferType::InferTypeKind::GENERAL)); } } } private: TypeCheckStmt (bool is_final_stmt) - : TypeCheckBase (), is_final_stmt (is_final_stmt) + : TypeCheckBase (), infered (nullptr), is_final_stmt (is_final_stmt) {} TyTy::TyBase *infered; diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index fcaf724..52b6cde 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -56,8 +56,7 @@ public: TyTy::TyBase *type = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (), - struct_decl.get_identifier (), true, - std::move (fields)); + struct_decl.get_identifier (), std::move (fields)); context->insert_type (struct_decl.get_mappings (), type); } @@ -78,8 +77,7 @@ public: TyTy::TyBase *type = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (), - struct_decl.get_identifier (), false, - std::move (fields)); + struct_decl.get_identifier (), std::move (fields)); context->insert_type (struct_decl.get_mappings (), type); } @@ -107,9 +105,15 @@ public: ret_type = new TyTy::UnitType (function.get_mappings ().get_hirid ()); else { - TyTy::InferType infer (function.get_mappings ().get_hirid ()); auto resolved = TypeCheckType::Resolve (function.return_type.get ()); - ret_type = infer.combine (resolved); + if (resolved == nullptr) + { + rust_error_at (function.get_locus (), + "failed to resolve return type"); + return; + } + + ret_type = resolved->clone (); ret_type->set_ref (function.return_type->get_mappings ().get_hirid ()); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index 579dfb0..e5d3898 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -40,11 +40,12 @@ public: void visit (HIR::LiteralExpr &expr) { + auto literal_value = expr.get_literal (); switch (expr.get_lit_type ()) { case HIR::Literal::LitType::INT: { ok = true; - std::stringstream ss (expr.as_string ()); + std::stringstream ss (literal_value->as_string ()); ss >> result; } break; @@ -70,8 +71,10 @@ public: type->accept_vis (resolver); if (resolver.translated != nullptr) - resolver.context->insert_type (type->get_mappings (), - resolver.translated); + { + resolver.context->insert_type (type->get_mappings (), + resolver.translated); + } return resolver.translated; } @@ -89,25 +92,15 @@ public: return; } - size_t index = 0; - std::string identifier = "("; - std::vector fields; + std::vector fields; for (auto &elem : tuple.get_elems ()) { auto field_ty = TypeCheckType::Resolve (elem.get ()); - identifier += field_ty->as_string (); - if ((index + 1) < tuple.get_elems ().size ()) - identifier += ","; - - auto field_tyty - = new TyTy::StructFieldType (elem->get_mappings ().get_hirid (), - std::to_string (index), field_ty); - fields.push_back (field_tyty); - index++; + fields.push_back (field_ty->get_ref ()); } - identifier += ")"; - translated = new TyTy::ADTType (tuple.get_mappings ().get_hirid (), - identifier, true, fields); + + translated + = new TyTy::TupleType (tuple.get_mappings ().get_hirid (), fields); } void visit (HIR::TypePath &path) @@ -129,6 +122,9 @@ public: // we got an HIR node if (context->lookup_type (hir_lookup, &translated)) { + translated = translated->clone (); + auto ref = path.get_mappings ().get_hirid (); + translated->set_ref (ref); return; } } diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index aa3d505..cf3a846 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -34,6 +34,54 @@ TypeResolution::Resolve (HIR::Crate &crate) for (auto it = crate.items.begin (); it != crate.items.end (); it++) TypeCheckItem::Resolve (it->get ()); + + auto mappings = Analysis::Mappings::get (); + auto context = TypeCheckContext::get (); + + context->iterate ([&] (HirId id, TyTy::TyBase *ty) mutable -> bool { + // nothing to do + if (ty->get_kind () != TyTy::TypeKind::INFER) + return true; + + TyTy::InferType *infer_var = (TyTy::InferType *) ty; + switch (infer_var->get_infer_kind ()) + { + case TyTy::InferType::GENERAL: + rust_error_at (mappings->lookup_location (id), + "unable to determine type: %u", id); + break; + + case TyTy::InferType::INTEGRAL: { + TyTy::TyBase *default_integer; + bool ok = context->lookup_builtin ("i32", &default_integer); + rust_assert (ok); + + auto result = ty->combine (default_integer); + result->set_ref (id); + context->insert_type ( + Analysis::NodeMapping (mappings->get_current_crate (), 0, id, + UNKNOWN_LOCAL_DEFID), + result); + } + break; + + case TyTy::InferType::FLOAT: { + TyTy::TyBase *default_float; + bool ok = context->lookup_builtin ("f32", &default_float); + rust_assert (ok); + + auto result = ty->combine (default_float); + result->set_ref (id); + context->insert_type ( + Analysis::NodeMapping (mappings->get_current_crate (), 0, id, + UNKNOWN_LOCAL_DEFID), + result); + } + break; + } + + return true; + }); } // RUST_HIR_TYPE_CHECK_EXPR @@ -48,6 +96,12 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) bool is_final_expr = is_final_stmt && !expr.has_expr (); auto infered = TypeCheckStmt::Resolve (s, is_final_expr); + if (infered == nullptr) + { + rust_error_at (s->get_locus_slow (), "failure to resolve type"); + return false; + } + if (is_final_expr) { delete block_tyty; @@ -59,21 +113,19 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) // tail expression must be checked as part of the caller since // the result of this is very dependant on what we expect it to be - if (expr.has_expr ()) - TypeCheckExpr::Resolve (expr.expr.get ()); // now that the stmts have been resolved we must resolve the block of locals // and make sure the variables have been resolved - auto body_mappings = expr.get_mappings (); - Rib *rib = nullptr; - if (!resolver->find_name_rib (body_mappings.get_nodeid (), &rib)) - { - rust_fatal_error (expr.get_locus (), "failed to lookup locals per block"); - return; - } - TyTyResolver::Resolve (rib, mappings, resolver, context); - - infered = block_tyty; + // auto body_mappings = expr.get_mappings (); + // Rib *rib = nullptr; + // if (!resolver->find_name_rib (body_mappings.get_nodeid (), &rib)) + // { + // rust_fatal_error (expr.get_locus (), "failed to lookup locals per + // block"); return; + // } + // TyTyResolver::Resolve (rib, mappings, resolver, context); + + infered = block_tyty->clone (); } // RUST_HIR_TYPE_CHECK_STRUCT_FIELD @@ -154,47 +206,23 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) = struct_expr.struct_base->base_struct->clone_expr_impl (); HIR::StructExprField *implicit_field = nullptr; - if (struct_path_resolved->is_tuple_struct ()) - { - std::vector outer_attribs; - TupleIndex tuple_index = std::stoi (missing); - - auto crate_num = mappings->get_current_crate (); - Analysis::NodeMapping mapping ( - crate_num, - struct_expr.struct_base->base_struct->get_mappings () - .get_nodeid (), - mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - - HIR::Expr *field_value = new HIR::TupleIndexExpr ( - mapping, std::unique_ptr (receiver), tuple_index, - std::move (outer_attribs), - struct_expr.struct_base->base_struct->get_locus_slow ()); - - implicit_field = new HIR::StructExprFieldIndexValue ( - mapping, tuple_index, - std::unique_ptr (field_value), - struct_expr.struct_base->base_struct->get_locus_slow ()); - } - else - { - std::vector outer_attribs; - auto crate_num = mappings->get_current_crate (); - Analysis::NodeMapping mapping ( - crate_num, - struct_expr.struct_base->base_struct->get_mappings () - .get_nodeid (), - mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - - HIR::Expr *field_value = new HIR::FieldAccessExpr ( - mapping, std::unique_ptr (receiver), missing, - std::move (outer_attribs), - struct_expr.struct_base->base_struct->get_locus_slow ()); - - implicit_field = new HIR::StructExprFieldIdentifierValue ( - mapping, missing, std::unique_ptr (field_value), - struct_expr.struct_base->base_struct->get_locus_slow ()); - } + + std::vector outer_attribs; + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping ( + crate_num, + struct_expr.struct_base->base_struct->get_mappings () + .get_nodeid (), + mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); + + HIR::Expr *field_value = new HIR::FieldAccessExpr ( + mapping, std::unique_ptr (receiver), missing, + std::move (outer_attribs), + struct_expr.struct_base->base_struct->get_locus_slow ()); + + implicit_field = new HIR::StructExprFieldIdentifierValue ( + mapping, missing, std::unique_ptr (field_value), + struct_expr.struct_base->base_struct->get_locus_slow ()); size_t field_index; bool ok = struct_path_resolved->get_field (missing, &field_index); diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index e0458a7..d033878 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -47,6 +47,15 @@ public: void push_return_type (TyTy::TyBase *return_type); void pop_return_type (); + void iterate (std::function cb) + { + for (auto it = resolved.begin (); it != resolved.end (); it++) + { + if (!cb (it->first, it->second)) + return; + } + } + private: TypeCheckContext (); diff --git a/gcc/rust/typecheck/rust-tycheck-dump.h b/gcc/rust/typecheck/rust-tycheck-dump.h new file mode 100644 index 0000000..863c2eb --- /dev/null +++ b/gcc/rust/typecheck/rust-tycheck-dump.h @@ -0,0 +1,178 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#ifndef RUST_TYCHECK_DUMP +#define RUST_TYCHECK_DUMP + +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" + +namespace Rust { +namespace Resolver { + +class TypeResolverDump : public TypeCheckBase +{ +public: + static std::string go (HIR::Crate &crate) + { + TypeResolverDump dumper; + for (auto &item : crate.items) + item->accept_vis (dumper); + + return dumper.dump; + } + + void visit (HIR::Function &function) + { + dump += indent () + "fn " + function.function_name + " " + + type_string (function.get_mappings ()) + "\n"; + dump += indent () + "{\n"; + + HIR::BlockExpr *function_body = function.function_body.get (); + function_body->accept_vis (*this); + + dump += indent () + "}\n"; + } + + void visit (HIR::BlockExpr &expr) + { + indentation_level++; + + expr.iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { + s->accept_vis (*this); + dump += ";\n"; + return true; + }); + + if (expr.has_expr () && expr.tail_expr_reachable ()) + { + expr.expr->accept_vis (*this); + dump += ";\n"; + } + + indentation_level--; + } + + void visit (HIR::LetStmt &stmt) + { + dump += indent () + "let " + stmt.get_pattern ()->as_string () + ":" + + type_string (stmt.get_mappings ()); + if (stmt.has_init_expr ()) + { + dump += " = "; + stmt.get_init_expr ()->accept_vis (*this); + } + } + + void visit (HIR::ExprStmtWithBlock &stmt) + { + dump += indent (); + stmt.get_expr ()->accept_vis (*this); + } + + void visit (HIR::ExprStmtWithoutBlock &stmt) + { + dump += indent (); + stmt.get_expr ()->accept_vis (*this); + } + + void visit (HIR::AssignmentExpr &expr) + { + expr.get_lhs ()->accept_vis (*this); + dump += " = "; + expr.get_rhs ()->accept_vis (*this); + } + + void visit (HIR::LiteralExpr &expr) + { + dump += expr.get_literal ()->as_string () + ":" + + type_string (expr.get_mappings ()); + } + + void visit (HIR::IdentifierExpr &expr) + { + dump += expr.get_identifier () + ":" + type_string (expr.get_mappings ()); + } + + void visit (HIR::ArrayExpr &expr) + { + dump += type_string (expr.get_mappings ()) + ":["; + + HIR::ArrayElems *elements = expr.get_internal_elements (); + elements->accept_vis (*this); + + dump += "]"; + } + + void visit (HIR::ArrayElemsValues &elems) + { + elems.iterate ([&] (HIR::Expr *e) mutable -> bool { + e->accept_vis (*this); + dump += ","; + return true; + }); + } + + void visit (HIR::GroupedExpr &expr) + { + HIR::Expr *paren_expr = expr.get_expr_in_parens ().get (); + dump += "("; + paren_expr->accept_vis (*this); + dump += ")"; + } + +protected: + std::string type_string (const Analysis::NodeMapping &mappings) + { + TyTy::TyBase *lookup = nullptr; + if (!context->lookup_type (mappings.get_hirid (), &lookup)) + return ""; + + std::string buf = "["; + for (auto &ref : lookup->get_combined_refs ()) + { + buf += std::to_string (ref); + buf += ", "; + } + buf += "]"; + + return "<" + lookup->as_string () + + " RF:" + std::to_string (lookup->get_ref ()) + " TF:" + + std::to_string (lookup->get_ty_ref ()) + +" - " + buf + ">"; + } + + std::string indent () + { + std::string buf; + for (size_t i = 0; i < indentation_level; ++i) + buf += " "; + + return buf; + } + +private: + TypeResolverDump () : TypeCheckBase (), indentation_level (0) {} + + std::string dump; + size_t indentation_level; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_TYCHECK_DUMP diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h index 2e98cbb..84cfdce 100644 --- a/gcc/rust/typecheck/rust-tyty-call.h +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -23,6 +23,7 @@ #include "rust-hir-full.h" #include "rust-tyty-visitor.h" #include "rust-tyty.h" +#include "rust-hir-type-check.h" namespace Rust { namespace TyTy { @@ -30,9 +31,10 @@ namespace TyTy { class TypeCheckCallExpr : private TyVisitor { public: - static TyBase *go (TyBase *ref, HIR::CallExpr &call) + static TyBase *go (TyBase *ref, HIR::CallExpr &call, + Resolver::TypeCheckContext *context) { - TypeCheckCallExpr checker (call); + TypeCheckCallExpr checker (call, context); ref->accept_vis (checker); return checker.resolved; } @@ -40,6 +42,7 @@ public: void visit (UnitType &type) override { gcc_unreachable (); } void visit (InferType &type) override { gcc_unreachable (); } + void visit (TupleType &type) override { gcc_unreachable (); } void visit (StructFieldType &type) override { gcc_unreachable (); } void visit (ArrayType &type) override { gcc_unreachable (); } void visit (BoolType &type) override { gcc_unreachable (); } @@ -55,10 +58,15 @@ public: void visit (FnType &type) override; private: - TypeCheckCallExpr (HIR::CallExpr &c) : resolved (nullptr), call (c) {} + TypeCheckCallExpr (HIR::CallExpr &c, Resolver::TypeCheckContext *context) + : resolved (nullptr), call (c), context (context), + mappings (Analysis::Mappings::get ()) + {} TyBase *resolved; HIR::CallExpr &call; + Resolver::TypeCheckContext *context; + Analysis::Mappings *mappings; }; } // namespace TyTy diff --git a/gcc/rust/typecheck/rust-tyty-resolver.h b/gcc/rust/typecheck/rust-tyty-resolver.h deleted file mode 100644 index d48952c..0000000 --- a/gcc/rust/typecheck/rust-tyty-resolver.h +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright (C) 2020 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#ifndef RUST_TYTY_RESOLVER -#define RUST_TYTY_RESOLVER - -#include "rust-system.h" -#include "rust-diagnostics.h" -#include "rust-hir-map.h" -#include "rust-name-resolver.h" -#include "rust-hir-type-check.h" -#include "rust-hir-full.h" -#include "rust-tyty-visitor.h" - -namespace Rust { -namespace Resolver { - -class TyTyResolver -{ -public: - static void Resolve (Rib *rib, Analysis::Mappings *mappings, - Resolver *resolver, TypeCheckContext *context) - { - TyTyResolver r (mappings, resolver, context); - r.go (rib); - } - - virtual ~TyTyResolver () {} - - void go (Rib *rib) - { - rib->iterate_decls ([&] (NodeId decl_node_id, - Location locus) mutable -> bool { - // type inference in rust means we need to gather and examine all - // references of this decl and combine each to make sure the type is - // correctly inferred. Consider the example: - // let mut x; x = 1; - // we can only say x is an infer variable then at the assignment - // we think x must be an integer - - bool ok = true; - std::vector gathered_types; - rib->iterate_references_for_def ( - decl_node_id, [&] (NodeId ref_node) mutable -> bool { - HirId hir_node_ref; - if (!mappings->lookup_node_to_hir (mappings->get_current_crate (), - ref_node, &hir_node_ref)) - { - rust_error_at (locus, - "failed to reserve lookup HIR node for reference"); - ok = false; - return false; - } - - TyTy::TyBase *resolved = nullptr; - if (!context->lookup_type (hir_node_ref, &resolved)) - { - // this could be an array/adt type - Definition d; - if (!resolver->lookup_definition (ref_node, &d)) - { - rust_error_at ( - locus, - "failed to lookup definition for referenced hir node"); - - ok = false; - return false; - } - - if (!mappings->lookup_node_to_hir (mappings->get_current_crate (), - d.parent, &hir_node_ref)) - { - rust_error_at (locus, - "failed to lookup HIR node for parent NodeId"); - - ok = false; - return false; - } - - if (!context->lookup_type (hir_node_ref, &resolved)) - { - rust_error_at ( - mappings->lookup_location (hir_node_ref), - "failed to lookup type for reference at node [%u]", - hir_node_ref); - - ok = false; - return false; - } - } - - gathered_types.push_back (resolved); - return true; - }); - - Definition d; - if (!resolver->lookup_definition (decl_node_id, &d)) - { - rust_error_at (locus, "Failed to lookup definition within rib"); - return false; - } - - HIR::Stmt *decl = nullptr; - if (!mappings->resolve_nodeid_to_stmt (d.parent, &decl)) - { - rust_error_at (locus, "Failed to resolve decl to HIR::Stmt"); - return false; - } - - TyTy::TyBase *resolved_type = nullptr; - if (!context->lookup_type (decl->get_mappings ().get_hirid (), - &resolved_type)) - { - rust_error_at (locus, "Unknown base type for decl in Rib"); - return false; - } - - // if it is not infer then it must have been figured out already - // we might need changes for generics later on - if (resolved_type->get_kind () != TyTy::TypeKind::INFER) - return true; - - auto resolved_tyty = resolved_type; - for (auto it : gathered_types) - { - auto combined = resolved_tyty->combine (it); - if (combined == nullptr) - { - rust_fatal_error (decl->get_locus_slow (), - "type-check resolver failed"); - break; - } - - resolved_tyty = combined; - } - - // something is not inferred we need to look at all references now - if (resolved_tyty == nullptr - || resolved_tyty->get_kind () == TyTy::TypeKind::INFER - || resolved_tyty->get_kind () == TyTy::TypeKind::ERROR) - { - rust_fatal_error (decl->get_locus_slow (), "failed to resolve type"); - return false; - } - - // insert the new resolved definition - context->insert_type (decl->get_mappings (), resolved_tyty); - return true; - }); - } - -protected: -private: - TyTyResolver (Analysis::Mappings *mappings, Resolver *resolver, - TypeCheckContext *context) - : mappings (mappings), resolver (resolver), context (context) - {} - - Analysis::Mappings *mappings; - Resolver *resolver; - TypeCheckContext *context; -}; - -class TyTyExtractorArray : public TyTy::TyVisitor -{ -public: - static TyTy::TyBase *ExtractElementTypeFromArray (TyTy::TyBase *base) - { - TyTyExtractorArray e; - base->accept_vis (e); - rust_assert (e.extracted != nullptr); - return e.extracted; - } - - virtual ~TyTyExtractorArray () {} - - void visit (TyTy::UnitType &type) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } - void visit (TyTy::ADTType &type) override { gcc_unreachable (); } - void visit (TyTy::FnType &type) override { gcc_unreachable (); } - void visit (TyTy::BoolType &type) override { gcc_unreachable (); } - void visit (TyTy::IntType &type) override { gcc_unreachable (); } - void visit (TyTy::UintType &type) override { gcc_unreachable (); } - void visit (TyTy::FloatType &type) override { gcc_unreachable (); } - void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } - - void visit (TyTy::ArrayType &type) override { extracted = type.get_type (); } - -private: - TyTyExtractorArray () : extracted (nullptr) {} - - TyTy::TyBase *extracted; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_TYTY_RESOLVER diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 241b9be..890931f 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -23,6 +23,7 @@ #include "rust-tyty.h" #include "rust-tyty-visitor.h" #include "rust-hir-map.h" +#include "rust-hir-type-check.h" namespace Rust { namespace TyTy { @@ -32,161 +33,306 @@ class BaseRules : public TyVisitor public: virtual ~BaseRules () {} + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + if (resolved != nullptr) + { + resolved->append_reference (base->get_ref ()); + resolved->append_reference (other->get_ref ()); + for (auto ref : base->get_combined_refs ()) + resolved->append_reference (ref); + for (auto ref : other->get_combined_refs ()) + resolved->append_reference (ref); + + bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER; + if (result_resolved) + { + for (auto &ref : resolved->get_combined_refs ()) + { + TyTy::TyBase *ref_tyty = nullptr; + bool ok = context->lookup_type (ref, &ref_tyty); + if (!ok) + continue; + + // if any of the types are inference variables lets fix them + if (ref_tyty->get_kind () == TyTy::TypeKind::INFER) + { + NodeId ref_node_id = UNKNOWN_NODEID; + context->insert_type ( + Analysis::NodeMapping (mappings->get_current_crate (), + ref_node_id, ref, + UNKNOWN_LOCAL_DEFID), + resolved->clone ()); + } + } + } + } + return resolved; + } + virtual void visit (UnitType &type) override { Location ref_locus = mappings->lookup_location (type.get_ref ()); - Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_error_at (def_locus, "declared here"); + } + + virtual void visit (TupleType &type) override + { + Location ref_locus = mappings->lookup_location (type.get_ref ()); + rust_error_at (ref_locus, "expected [%s] got [%s]", + base->as_string ().c_str (), type.as_string ().c_str ()); } virtual void visit (ADTType &type) override { Location ref_locus = mappings->lookup_location (type.get_ref ()); - Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_error_at (def_locus, "declared here"); } virtual void visit (InferType &type) override { Location ref_locus = mappings->lookup_location (type.get_ref ()); - Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_error_at (def_locus, "declared here"); } virtual void visit (FnType &type) override { Location ref_locus = mappings->lookup_location (type.get_ref ()); - Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_error_at (def_locus, "declared here"); } virtual void visit (ArrayType &type) override { Location ref_locus = mappings->lookup_location (type.get_ref ()); - Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_error_at (def_locus, "declared here"); } virtual void visit (BoolType &type) override { Location ref_locus = mappings->lookup_location (type.get_ref ()); - Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_error_at (def_locus, "declared here"); } virtual void visit (IntType &type) override { Location ref_locus = mappings->lookup_location (type.get_ref ()); - Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_error_at (def_locus, "declared here"); } virtual void visit (UintType &type) override { Location ref_locus = mappings->lookup_location (type.get_ref ()); - Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_error_at (def_locus, "declared here"); } virtual void visit (FloatType &type) override { Location ref_locus = mappings->lookup_location (type.get_ref ()); - Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_error_at (def_locus, "declared here"); } virtual void visit (ErrorType &type) override { Location ref_locus = mappings->lookup_location (type.get_ref ()); - Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_error_at (def_locus, "declared here"); } virtual void visit (StructFieldType &type) override { Location ref_locus = mappings->lookup_location (type.get_ref ()); - Location def_locus = mappings->lookup_location (base->get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", base->as_string ().c_str (), type.as_string ().c_str ()); - rust_error_at (def_locus, "declared here"); } protected: BaseRules (TyBase *base) - : mappings (Analysis::Mappings::get ()), base (base), + : mappings (Analysis::Mappings::get ()), + context (Resolver::TypeCheckContext::get ()), base (base), resolved (new ErrorType (base->get_ref (), base->get_ref ())) {} Analysis::Mappings *mappings; + Resolver::TypeCheckContext *context; + TyBase *base; TyBase *resolved; }; -class InferRules : protected BaseRules +class InferRules : public BaseRules { public: InferRules (InferType *base) : BaseRules (base), base (base) {} - TyBase *combine (TyBase *other) + void visit (UnitType &type) override { - other->accept_vis (*this); - return resolved; + bool is_valid + = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); + if (is_valid) + { + resolved = type.clone (); + return; + } + + BaseRules::visit (type); + } + + void visit (BoolType &type) override + { + bool is_valid + = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); + if (is_valid) + { + resolved = type.clone (); + return; + } + + BaseRules::visit (type); + } + + void visit (IntType &type) override + { + bool is_valid + = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) + || (base->get_infer_kind () + == TyTy::InferType::InferTypeKind::INTEGRAL); + if (is_valid) + { + resolved = type.clone (); + return; + } + + BaseRules::visit (type); + } + + void visit (UintType &type) override + { + bool is_valid + = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) + || (base->get_infer_kind () + == TyTy::InferType::InferTypeKind::INTEGRAL); + if (is_valid) + { + resolved = type.clone (); + return; + } + + BaseRules::visit (type); + } + + void visit (FloatType &type) override + { + bool is_valid + = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) + || (base->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT); + if (is_valid) + { + resolved = type.clone (); + return; + } + + BaseRules::visit (type); } - // we are an inference variable so this means we can take the other as the - // type - void visit (InferType &type) override { resolved = type.clone (); } + void visit (ArrayType &type) override + { + bool is_valid + = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); + if (is_valid) + { + resolved = type.clone (); + return; + } + + BaseRules::visit (type); + } - void visit (UnitType &type) override { resolved = type.clone (); } + void visit (ADTType &type) override + { + bool is_valid + = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); + if (is_valid) + { + resolved = type.clone (); + return; + } - void visit (BoolType &type) override { resolved = type.clone (); } + BaseRules::visit (type); + } - void visit (IntType &type) override { resolved = type.clone (); } + void visit (TupleType &type) override + { + bool is_valid + = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); + if (is_valid) + { + resolved = type.clone (); + return; + } - void visit (UintType &type) override { resolved = type.clone (); } + BaseRules::visit (type); + } - void visit (FloatType &type) override { resolved = type.clone (); } + void visit (InferType &type) override + { + switch (base->get_infer_kind ()) + { + case InferType::InferTypeKind::GENERAL: + resolved = type.clone (); + return; - void visit (ArrayType &type) override { resolved = type.clone (); } + case InferType::InferTypeKind::INTEGRAL: { + if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL) + { + resolved = type.clone (); + return; + } + else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL) + { + resolved = base->clone (); + return; + } + } + break; + + case InferType::InferTypeKind::FLOAT: { + if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) + { + resolved = type.clone (); + return; + } + else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL) + { + resolved = base->clone (); + return; + } + } + break; + } - void visit (ADTType &type) override { resolved = type.clone (); } + BaseRules::visit (type); + } private: InferType *base; }; -class StructFieldTypeRules : protected BaseRules +class StructFieldTypeRules : public BaseRules { public: StructFieldTypeRules (StructFieldType *base) : BaseRules (base), base (base) {} - TyBase *combine (TyBase *other) - { - other->accept_vis (*this); - return resolved; - } - void visit (StructFieldType &type) { TyBase *ty = base->get_field_type ()->combine (type.get_field_type ()); @@ -201,17 +347,11 @@ private: StructFieldType *base; }; -class UnitRules : protected BaseRules +class UnitRules : public BaseRules { public: UnitRules (UnitType *base) : BaseRules (base), base (base) {} - TyBase *combine (TyBase *other) - { - other->accept_vis (*this); - return resolved; - } - void visit (UnitType &type) override { resolved = new UnitType (type.get_ref (), type.get_ty_ref ()); @@ -221,44 +361,36 @@ private: UnitType *base; }; -class FnRules : protected BaseRules +class FnRules : public BaseRules { public: FnRules (FnType *base) : BaseRules (base), base (base) {} - TyBase *combine (TyBase *other) - { - other->accept_vis (*this); - return resolved; - } - private: FnType *base; }; -class ArrayRules : protected BaseRules +class ArrayRules : public BaseRules { public: ArrayRules (ArrayType *base) : BaseRules (base), base (base) {} - TyBase *combine (TyBase *other) - { - other->accept_vis (*this); - return resolved; - } - void visit (ArrayType &type) override { // check base type auto base_resolved = base->get_type ()->combine (type.get_type ()); if (base_resolved == nullptr) - return; + { + // fixme add error message + return; + } // need to check the base types and capacity if (type.get_capacity () != base->get_capacity ()) { Location locus = mappings->lookup_location (type.get_ref ()); rust_error_at (locus, "mismatch in array capacity"); + BaseRules::visit (type); return; } @@ -270,17 +402,11 @@ private: ArrayType *base; }; -class BoolRules : protected BaseRules +class BoolRules : public BaseRules { public: BoolRules (BoolType *base) : BaseRules (base), base (base) {} - TyBase *combine (TyBase *other) - { - other->accept_vis (*this); - return resolved; - } - void visit (BoolType &type) override { resolved = new BoolType (type.get_ref (), type.get_ty_ref ()); @@ -290,15 +416,22 @@ private: BoolType *base; }; -class IntRules : protected BaseRules +class IntRules : public BaseRules { public: IntRules (IntType *base) : BaseRules (base), base (base) {} - TyBase *combine (TyBase *other) + void visit (InferType &type) override { - other->accept_vis (*this); - return resolved; + // cant assign a float inference variable + if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) + { + BaseRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); } void visit (IntType &type) override @@ -317,15 +450,22 @@ private: IntType *base; }; -class UintRules : protected BaseRules +class UintRules : public BaseRules { public: UintRules (UintType *base) : BaseRules (base), base (base) {} - TyBase *combine (TyBase *other) + void visit (InferType &type) override { - other->accept_vis (*this); - return resolved; + // cant assign a float inference variable + if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) + { + BaseRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); } void visit (UintType &type) override @@ -344,15 +484,21 @@ private: UintType *base; }; -class FloatRules : protected BaseRules +class FloatRules : public BaseRules { public: FloatRules (FloatType *base) : BaseRules (base), base (base) {} - TyBase *combine (TyBase *other) + void visit (InferType &type) override { - other->accept_vis (*this); - return resolved; + if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL) + { + BaseRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); } void visit (FloatType &type) override @@ -371,17 +517,11 @@ private: FloatType *base; }; -class ADTRules : protected BaseRules +class ADTRules : public BaseRules { public: ADTRules (ADTType *base) : BaseRules (base), base (base) {} - TyBase *combine (TyBase *other) - { - other->accept_vis (*this); - return resolved; - } - void visit (ADTType &type) { if (base->num_fields () != type.num_fields ()) @@ -390,12 +530,6 @@ public: return; } - if (base->get_name ().compare (type.get_name ()) != 0) - { - BaseRules::visit (type); - return; - } - std::vector fields; for (size_t i = 0; i < type.num_fields (); ++i) { @@ -412,15 +546,51 @@ public: fields.push_back ((TyTy::StructFieldType *) combined); } - resolved - = new TyTy::ADTType (type.get_ref (), type.get_ty_ref (), - type.get_name (), type.is_tuple_struct (), fields); + resolved = new TyTy::ADTType (type.get_ref (), type.get_ty_ref (), + type.get_name (), fields); } private: ADTType *base; }; +class TupleRules : public BaseRules +{ +public: + TupleRules (TupleType *base) : BaseRules (base), base (base) {} + + void visit (TupleType &type) + { + if (base->num_fields () != type.num_fields ()) + { + BaseRules::visit (type); + return; + } + + std::vector fields; + for (size_t i = 0; i < base->num_fields (); i++) + { + TyBase *bo = base->get_field (i); + TyBase *fo = type.get_field (i); + + TyBase *combined = bo->combine (fo); + if (combined == nullptr) + { + BaseRules::visit (type); + return; + } + + fields.push_back (combined->get_ref ()); + } + + resolved + = new TyTy::TupleType (type.get_ref (), type.get_ty_ref (), fields); + } + +private: + TupleType *base; +}; + } // namespace TyTy } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h index b6759dd..3997295 100644 --- a/gcc/rust/typecheck/rust-tyty-visitor.h +++ b/gcc/rust/typecheck/rust-tyty-visitor.h @@ -31,6 +31,7 @@ public: virtual void visit (InferType &type) = 0; virtual void visit (StructFieldType &type) = 0; virtual void visit (ADTType &type) = 0; + virtual void visit (TupleType &type) = 0; virtual void visit (FnType &type) = 0; virtual void visit (ArrayType &type) = 0; virtual void visit (BoolType &type) = 0; diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 2e09de6..9efde68 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -47,7 +47,7 @@ UnitType::combine (TyBase *other) TyBase * UnitType::clone () { - return new UnitType (get_ref (), get_ty_ref ()); + return new UnitType (get_ref (), get_ty_ref (), get_combined_refs ()); } void @@ -59,7 +59,16 @@ InferType::accept_vis (TyVisitor &vis) std::string InferType::as_string () const { - return "?"; + switch (infer_kind) + { + case GENERAL: + return "T?"; + case INTEGRAL: + return ""; + case FLOAT: + return ""; + } + return ""; } TyBase * @@ -72,7 +81,8 @@ InferType::combine (TyBase *other) TyBase * InferType::clone () { - return new InferType (get_ref (), get_ty_ref ()); + return new InferType (get_ref (), get_ty_ref (), get_infer_kind (), + get_combined_refs ()); } void @@ -98,7 +108,7 @@ ErrorType::combine (TyBase *other) TyBase * ErrorType::clone () { - return new ErrorType (get_ref ()); + return new ErrorType (get_ref (), get_ty_ref (), get_combined_refs ()); } void @@ -124,7 +134,8 @@ TyBase * StructFieldType::clone () { return new StructFieldType (get_ref (), get_ty_ref (), get_name (), - get_field_type ()->clone ()); + get_field_type ()->clone (), + get_combined_refs ()); } void @@ -157,8 +168,50 @@ ADTType::clone () for (auto &f : fields) cloned_fields.push_back ((StructFieldType *) f->clone ()); - return new ADTType (get_ref (), get_ty_ref (), get_name (), - is_tuple_struct (), cloned_fields); + return new ADTType (get_ref (), get_ty_ref (), get_name (), cloned_fields, + get_combined_refs ()); +} + +void +TupleType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +TupleType::as_string () const +{ + std::string fields_buffer; + iterate_fields ([&] (TyBase *field) mutable -> bool { + fields_buffer += field->as_string (); + fields_buffer += ", "; + return true; + }); + return "(" + fields_buffer + ")"; +} + +TyBase * +TupleType::get_field (size_t index) const +{ + auto context = Resolver::TypeCheckContext::get (); + TyBase *lookup = nullptr; + bool ok = context->lookup_type (fields.at (index), &lookup); + rust_assert (ok); + return lookup; +} + +TyBase * +TupleType::combine (TyBase *other) +{ + TupleRules r (this); + return r.combine (other); +} + +TyBase * +TupleType::clone () +{ + return new TupleType (get_ref (), get_ty_ref (), fields, + get_combined_refs ()); } void @@ -199,7 +252,7 @@ FnType::clone () std::pair (p.first, p.second->clone ())); return new FnType (get_ref (), get_ty_ref (), cloned_params, - get_return_type ()->clone ()); + get_return_type ()->clone (), get_combined_refs ()); } void @@ -211,7 +264,8 @@ ArrayType::accept_vis (TyVisitor &vis) std::string ArrayType::as_string () const { - return "[" + type->as_string () + ":" + std::to_string (capacity) + "]"; + return "[" + get_type ()->as_string () + ":" + std::to_string (capacity) + + "]"; } TyBase * @@ -222,10 +276,20 @@ ArrayType::combine (TyBase *other) } TyBase * +ArrayType::get_type () const +{ + auto context = Resolver::TypeCheckContext::get (); + TyBase *lookup = nullptr; + bool ok = context->lookup_type (element_type_id, &lookup); + rust_assert (ok); + return lookup; +} + +TyBase * ArrayType::clone () { return new ArrayType (get_ref (), get_ty_ref (), get_capacity (), - get_type ()->clone ()); + get_type ()->clone (), get_combined_refs ()); } void @@ -250,7 +314,7 @@ BoolType::combine (TyBase *other) TyBase * BoolType::clone () { - return new BoolType (get_ref (), get_ty_ref ()); + return new BoolType (get_ref (), get_ty_ref (), get_combined_refs ()); } void @@ -289,7 +353,8 @@ IntType::combine (TyBase *other) TyBase * IntType::clone () { - return new IntType (get_ref (), get_ty_ref (), get_kind ()); + return new IntType (get_ref (), get_ty_ref (), get_kind (), + get_combined_refs ()); } void @@ -328,7 +393,8 @@ UintType::combine (TyBase *other) TyBase * UintType::clone () { - return new UintType (get_ref (), get_ty_ref (), get_kind ()); + return new UintType (get_ref (), get_ty_ref (), get_kind (), + get_combined_refs ()); } void @@ -361,18 +427,13 @@ FloatType::combine (TyBase *other) TyBase * FloatType::clone () { - return new FloatType (get_ref (), get_ty_ref (), get_kind ()); + return new FloatType (get_ref (), get_ty_ref (), get_kind (), + get_combined_refs ()); } void TypeCheckCallExpr::visit (ADTType &type) { - if (!type.is_tuple_struct ()) - { - rust_error_at (call.get_locus (), "Expected TupleStruct"); - return; - } - if (call.num_params () != type.num_fields ()) { rust_error_at (call.get_locus (), @@ -425,21 +486,26 @@ TypeCheckCallExpr::visit (FnType &type) } size_t i = 0; - call.iterate_params ([&] (HIR::Expr *p) mutable -> bool { + call.iterate_params ([&] (HIR::Expr *param) mutable -> bool { auto fnparam = type.param_at (i); - auto t = Resolver::TypeCheckExpr::Resolve (p); - if (t == nullptr) + auto argument_expr_tyty = Resolver::TypeCheckExpr::Resolve (param); + if (argument_expr_tyty == nullptr) { - rust_error_at (p->get_locus_slow (), "failed to resolve type"); + rust_error_at (param->get_locus_slow (), + "failed to resolve type for argument expr in CallExpr"); return false; } - auto pt = fnparam.second; - auto res = pt->combine (t); - if (res == nullptr) - return false; + auto resolved_argument_type = fnparam.second->combine (argument_expr_tyty); + if (resolved_argument_type == nullptr) + { + rust_error_at (param->get_locus_slow (), + "Type Resolution failure on parameter"); + return false; + } + + context->insert_type (param->get_mappings (), resolved_argument_type); - delete res; i++; return true; }); @@ -452,7 +518,7 @@ TypeCheckCallExpr::visit (FnType &type) return; } - resolved = type.get_return_type (); + resolved = type.get_return_type ()->clone (); } } // namespace TyTy diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index a73a344..6c6f27c 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -24,6 +24,7 @@ namespace Rust { namespace TyTy { +// https://rustc-dev-guide.rust-lang.org/type-inference.html#inference-variables // https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variants enum TypeKind { @@ -72,22 +73,42 @@ public: virtual TyBase *clone () = 0; + std::set get_combined_refs () { return combined; } + + void append_reference (HirId id) { combined.insert (id); } + protected: - TyBase (HirId ref, HirId ty_ref, TypeKind kind) - : kind (kind), ref (ref), ty_ref (ty_ref) + TyBase (HirId ref, HirId ty_ref, TypeKind kind, + std::set refs = std::set ()) + : kind (kind), ref (ref), ty_ref (ty_ref), combined (refs) {} TypeKind kind; HirId ref; HirId ty_ref; + + std::set combined; }; class InferType : public TyBase { public: - InferType (HirId ref) : TyBase (ref, ref, TypeKind::INFER) {} + enum InferTypeKind + { + GENERAL, + INTEGRAL, + FLOAT + }; + + InferType (HirId ref, InferTypeKind infer_kind, + std::set refs = std::set ()) + : TyBase (ref, ref, TypeKind::INFER, refs), infer_kind (infer_kind) + {} - InferType (HirId ref, HirId ty_ref) : TyBase (ref, ty_ref, TypeKind::INFER) {} + InferType (HirId ref, HirId ty_ref, InferTypeKind infer_kind, + std::set refs = std::set ()) + : TyBase (ref, ty_ref, TypeKind::INFER, refs), infer_kind (infer_kind) + {} void accept_vis (TyVisitor &vis) override; @@ -98,14 +119,23 @@ public: TyBase *combine (TyBase *other) override; TyBase *clone () final override; + + InferTypeKind get_infer_kind () const { return infer_kind; } + +private: + InferTypeKind infer_kind; }; class ErrorType : public TyBase { public: - ErrorType (HirId ref) : TyBase (ref, ref, TypeKind::ERROR) {} + ErrorType (HirId ref, std::set refs = std::set ()) + : TyBase (ref, ref, TypeKind::ERROR, refs) + {} - ErrorType (HirId ref, HirId ty_ref) : TyBase (ref, ty_ref, TypeKind::ERROR) {} + ErrorType (HirId ref, HirId ty_ref, std::set refs = std::set ()) + : TyBase (ref, ty_ref, TypeKind::ERROR, refs) + {} void accept_vis (TyVisitor &vis) override; @@ -121,9 +151,13 @@ public: class UnitType : public TyBase { public: - UnitType (HirId ref) : TyBase (ref, ref, TypeKind::UNIT) {} + UnitType (HirId ref, std::set refs = std::set ()) + : TyBase (ref, ref, TypeKind::UNIT, refs) + {} - UnitType (HirId ref, HirId ty_ref) : TyBase (ref, ty_ref, TypeKind::UNIT) {} + UnitType (HirId ref, HirId ty_ref, std::set refs = std::set ()) + : TyBase (ref, ty_ref, TypeKind::UNIT, refs) + {} void accept_vis (TyVisitor &vis) override; @@ -139,12 +173,14 @@ public: class StructFieldType : public TyBase { public: - StructFieldType (HirId ref, std::string name, TyBase *ty) - : TyBase (ref, ref, TypeKind::FIELD), name (name), ty (ty) + StructFieldType (HirId ref, std::string name, TyBase *ty, + std::set refs = std::set ()) + : TyBase (ref, ref, TypeKind::FIELD, refs), name (name), ty (ty) {} - StructFieldType (HirId ref, HirId ty_ref, std::string name, TyBase *ty) - : TyBase (ref, ty_ref, TypeKind::FIELD), name (name), ty (ty) + StructFieldType (HirId ref, HirId ty_ref, std::string name, TyBase *ty, + std::set refs = std::set ()) + : TyBase (ref, ty_ref, TypeKind::FIELD, refs), name (name), ty (ty) {} void accept_vis (TyVisitor &vis) override; @@ -166,19 +202,61 @@ private: TyBase *ty; }; +class TupleType : public TyBase +{ +public: + TupleType (HirId ref, std::vector fields, + std::set refs = std::set ()) + : TyBase (ref, ref, TypeKind::TUPLE, refs), fields (fields) + {} + + TupleType (HirId ref, HirId ty_ref, std::vector fields, + std::set refs = std::set ()) + : TyBase (ref, ty_ref, TypeKind::TUPLE, refs), fields (fields) + {} + + void accept_vis (TyVisitor &vis) override; + + bool is_unit () const override { return false; } + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; + + size_t num_fields () const { return fields.size (); } + + TyBase *get_field (size_t index) const; + + TyBase *clone () final override; + + void iterate_fields (std::function cb) const + { + for (size_t i = 0; i < num_fields (); i++) + { + if (!cb (get_field (i))) + return; + } + } + +private: + std::vector fields; +}; + class ADTType : public TyBase { public: - ADTType (HirId ref, std::string identifier, bool is_tuple, - std::vector fields) - : TyBase (ref, ref, TypeKind::ADT), identifier (identifier), - is_tuple (is_tuple), fields (fields) + ADTType (HirId ref, std::string identifier, + std::vector fields, + std::set refs = std::set ()) + : TyBase (ref, ref, TypeKind::ADT, refs), identifier (identifier), + fields (fields) {} - ADTType (HirId ref, HirId ty_ref, std::string identifier, bool is_tuple, - std::vector fields) - : TyBase (ref, ty_ref, TypeKind::ADT), identifier (identifier), - is_tuple (is_tuple), fields (fields) + ADTType (HirId ref, HirId ty_ref, std::string identifier, + std::vector fields, + std::set refs = std::set ()) + : TyBase (ref, ty_ref, TypeKind::ADT, refs), identifier (identifier), + fields (fields) {} void accept_vis (TyVisitor &vis) override; @@ -193,8 +271,6 @@ public: std::string get_name () const { return identifier; } - bool is_tuple_struct () const { return is_tuple; } - StructFieldType *get_field (size_t index) { return fields.at (index); } StructFieldType *get_field (const std::string &lookup, @@ -230,7 +306,6 @@ public: private: std::string identifier; - bool is_tuple; std::vector fields; }; @@ -238,15 +313,15 @@ class FnType : public TyBase { public: FnType (HirId ref, std::vector > params, - TyBase *type) - : TyBase (ref, ref, TypeKind::FNDEF), params (std::move (params)), + TyBase *type, std::set refs = std::set ()) + : TyBase (ref, ref, TypeKind::FNDEF, refs), params (std::move (params)), type (type) {} FnType (HirId ref, HirId ty_ref, std::vector > params, - TyBase *type) - : TyBase (ref, ty_ref, TypeKind::FNDEF), params (params), type (type) + TyBase *type, std::set refs = std::set ()) + : TyBase (ref, ty_ref, TypeKind::FNDEF, refs), params (params), type (type) {} void accept_vis (TyVisitor &vis) override; @@ -281,12 +356,16 @@ private: class ArrayType : public TyBase { public: - ArrayType (HirId ref, size_t capacity, TyBase *type) - : TyBase (ref, ref, TypeKind::ARRAY), capacity (capacity), type (type) + ArrayType (HirId ref, size_t capacity, TyBase *type, + std::set refs = std::set ()) + : TyBase (ref, ref, TypeKind::ARRAY, refs), capacity (capacity), + element_type_id (type->get_ref ()) {} - ArrayType (HirId ref, HirId ty_ref, size_t capacity, TyBase *type) - : TyBase (ref, ty_ref, TypeKind::ARRAY), capacity (capacity), type (type) + ArrayType (HirId ref, HirId ty_ref, size_t capacity, TyBase *type, + std::set refs = std::set ()) + : TyBase (ref, ty_ref, TypeKind::ARRAY, refs), capacity (capacity), + element_type_id (type->get_ref ()) {} void accept_vis (TyVisitor &vis) override; @@ -297,21 +376,27 @@ public: size_t get_capacity () const { return capacity; } - TyBase *get_type () { return type; } + HirId element_type_ref () const { return element_type_id; } + + TyBase *get_type () const; TyBase *clone () final override; private: size_t capacity; - TyBase *type; + HirId element_type_id; }; class BoolType : public TyBase { public: - BoolType (HirId ref) : TyBase (ref, ref, TypeKind::BOOL) {} + BoolType (HirId ref, std::set refs = std::set ()) + : TyBase (ref, ref, TypeKind::BOOL, refs) + {} - BoolType (HirId ref, HirId ty_ref) : TyBase (ref, ty_ref, TypeKind::BOOL) {} + BoolType (HirId ref, HirId ty_ref, std::set refs = std::set ()) + : TyBase (ref, ty_ref, TypeKind::BOOL, refs) + {} void accept_vis (TyVisitor &vis) override; @@ -334,12 +419,13 @@ public: I128 }; - IntType (HirId ref, IntKind kind) - : TyBase (ref, ref, TypeKind::INT), int_kind (kind) + IntType (HirId ref, IntKind kind, std::set refs = std::set ()) + : TyBase (ref, ref, TypeKind::INT, refs), int_kind (kind) {} - IntType (HirId ref, HirId ty_ref, IntKind kind) - : TyBase (ref, ty_ref, TypeKind::INT), int_kind (kind) + IntType (HirId ref, HirId ty_ref, IntKind kind, + std::set refs = std::set ()) + : TyBase (ref, ty_ref, TypeKind::INT, refs), int_kind (kind) {} void accept_vis (TyVisitor &vis) override; @@ -368,12 +454,13 @@ public: U128 }; - UintType (HirId ref, UintKind kind) - : TyBase (ref, ref, TypeKind::UINT), uint_kind (kind) + UintType (HirId ref, UintKind kind, std::set refs = std::set ()) + : TyBase (ref, ref, TypeKind::UINT, refs), uint_kind (kind) {} - UintType (HirId ref, HirId ty_ref, UintKind kind) - : TyBase (ref, ty_ref, TypeKind::UINT), uint_kind (kind) + UintType (HirId ref, HirId ty_ref, UintKind kind, + std::set refs = std::set ()) + : TyBase (ref, ty_ref, TypeKind::UINT, refs), uint_kind (kind) {} void accept_vis (TyVisitor &vis) override; @@ -399,12 +486,14 @@ public: F64 }; - FloatType (HirId ref, FloatKind kind) - : TyBase (ref, ref, TypeKind::FLOAT), float_kind (kind) + FloatType (HirId ref, FloatKind kind, + std::set refs = std::set ()) + : TyBase (ref, ref, TypeKind::FLOAT, refs), float_kind (kind) {} - FloatType (HirId ref, HirId ty_ref, FloatKind kind) - : TyBase (ref, ty_ref, TypeKind::FLOAT), float_kind (kind) + FloatType (HirId ref, HirId ty_ref, FloatKind kind, + std::set refs = std::set ()) + : TyBase (ref, ty_ref, TypeKind::FLOAT, refs), float_kind (kind) {} void accept_vis (TyVisitor &vis) override; diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index 951bdcc..925130f 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -159,6 +159,7 @@ Mappings::get_next_hir_id (CrateNum crateNum) auto id = it->second + 1; hirIdIter[crateNum] = id; + hirNodesWithinCrate[crateNum].insert (id); return id; } diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index 3818be9..4859d1e 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -143,6 +143,11 @@ public: return resolve_nodeid_to_stmt (get_current_crate (), id, stmt); } + std::set &get_hirids_within_crate (CrateNum crate) + { + return hirNodesWithinCrate[crate]; + } + private: Mappings (); @@ -171,6 +176,9 @@ private: // reverse mappings std::map > nodeIdToHirMappings; + + // all hirid nodes + std::map > hirNodesWithinCrate; }; } // namespace Analysis -- cgit v1.1 From 854aad3b58e747cad3e46b522c9ef765bdfadca4 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 25 Jan 2021 13:27:50 +0000 Subject: Add usize and isize types Arrays can only be indexed by usize and this enforces that rule. These types are sized based on the pointer size of the host arch. Fixes #87 --- gcc/rust/backend/rust-compile-context.h | 16 +++++ gcc/rust/backend/rust-compile-tyty.h | 14 ++++ gcc/rust/resolve/rust-ast-resolve.cc | 4 ++ gcc/rust/rust-backend.h | 3 + gcc/rust/rust-gcc.cc | 8 +++ gcc/rust/typecheck/rust-hir-type-check-expr.h | 2 +- gcc/rust/typecheck/rust-tyty-call.h | 2 + gcc/rust/typecheck/rust-tyty-rules.h | 92 +++++++++++++++++++++++++++ gcc/rust/typecheck/rust-tyty-visitor.h | 2 + gcc/rust/typecheck/rust-tyty.cc | 50 +++++++++++++++ gcc/rust/typecheck/rust-tyty.h | 42 ++++++++++++ 11 files changed, 234 insertions(+), 1 deletion(-) (limited to 'gcc/rust') diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index ed03f02..034568f 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -374,6 +374,22 @@ public: translated = compiled_type; } + void visit (TyTy::USizeType &type) override + { + ::Btype *compiled_type = nullptr; + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); + rust_assert (ok); + translated = compiled_type; + } + + void visit (TyTy::ISizeType &type) override + { + ::Btype *compiled_type = nullptr; + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); + rust_assert (ok); + translated = compiled_type; + } + private: TyTyResolveCompile (Context *ctx) : ctx (ctx) {} diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index b6794bc..2c54b17 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -190,6 +190,20 @@ public: gcc_unreachable (); } + void visit (TyTy::USizeType &type) override + { + translated = backend->named_type ( + "usize", backend->integer_type (true, backend->get_pointer_size ()), + Linemap::predeclared_location ()); + } + + void visit (TyTy::ISizeType &type) override + { + translated = backend->named_type ( + "isize", backend->integer_type (false, backend->get_pointer_size ()), + Linemap::predeclared_location ()); + } + private: TyTyCompile (::Backend *backend) : backend (backend), translated (nullptr), diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index ec53ae0..c6d7148 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -146,6 +146,8 @@ Resolver::generate_builtins () = new TyTy::FloatType (mappings->get_next_hir_id (), TyTy::FloatType::F32); auto f64 = new TyTy::FloatType (mappings->get_next_hir_id (), TyTy::FloatType::F64); + auto usize = new TyTy::USizeType (mappings->get_next_hir_id ()); + auto isize = new TyTy::ISizeType (mappings->get_next_hir_id ()); MKBUILTIN_TYPE ("u8", builtins, u8); MKBUILTIN_TYPE ("u16", builtins, u16); @@ -160,6 +162,8 @@ Resolver::generate_builtins () MKBUILTIN_TYPE ("bool", builtins, rbool); MKBUILTIN_TYPE ("f32", builtins, f32); MKBUILTIN_TYPE ("f64", builtins, f64); + MKBUILTIN_TYPE ("usize", builtins, usize); + MKBUILTIN_TYPE ("isize", builtins, isize); // unit type () TyTy::UnitType *unit_tyty = new TyTy::UnitType (mappings->get_next_hir_id ()); diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index 184f8fa..7b0ccf9 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -98,6 +98,9 @@ public: // Get the unnamed boolean type. virtual Btype *bool_type () = 0; + // Get the Host pointer size in bits + virtual int get_pointer_size () = 0; + // Get an unnamed integer type with the given signedness and number // of bits. virtual Btype *integer_type (bool is_unsigned, int bits) = 0; diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 6f8dc46..0729b1e 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -165,6 +165,8 @@ public: Btype *bool_type () { return this->make_type (boolean_type_node); } + int get_pointer_size (); + Btype *integer_type (bool, int); Btype *float_type (int); @@ -758,6 +760,12 @@ Gcc_backend::Gcc_backend () // Get an unnamed integer type. +int +Gcc_backend::get_pointer_size () +{ + return POINTER_SIZE; +} + Btype * Gcc_backend::integer_type (bool is_unsigned, int bits) { diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 8f60f72..17f1611 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -631,7 +631,7 @@ public: void visit (HIR::ArrayIndexExpr &expr) { TyTy::TyBase *size_ty; - if (!context->lookup_builtin ("i32", &size_ty)) + if (!context->lookup_builtin ("usize", &size_ty)) { rust_error_at ( expr.get_locus (), diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h index 84cfdce..2b3cfb6 100644 --- a/gcc/rust/typecheck/rust-tyty-call.h +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -49,6 +49,8 @@ public: void visit (IntType &type) override { gcc_unreachable (); } void visit (UintType &type) override { gcc_unreachable (); } void visit (FloatType &type) override { gcc_unreachable (); } + void visit (USizeType &type) override { gcc_unreachable (); } + void visit (ISizeType &type) override { gcc_unreachable (); } void visit (ErrorType &type) override { gcc_unreachable (); } // tuple-structs diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 890931f..e17cec7 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -134,6 +134,20 @@ public: base->as_string ().c_str (), type.as_string ().c_str ()); } + virtual void visit (USizeType &type) override + { + Location ref_locus = mappings->lookup_location (type.get_ref ()); + rust_error_at (ref_locus, "expected [%s] got [%s]", + base->as_string ().c_str (), type.as_string ().c_str ()); + } + + virtual void visit (ISizeType &type) override + { + Location ref_locus = mappings->lookup_location (type.get_ref ()); + rust_error_at (ref_locus, "expected [%s] got [%s]", + base->as_string ().c_str (), type.as_string ().c_str ()); + } + virtual void visit (FloatType &type) override { Location ref_locus = mappings->lookup_location (type.get_ref ()); @@ -230,6 +244,36 @@ public: BaseRules::visit (type); } + void visit (USizeType &type) override + { + bool is_valid + = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) + || (base->get_infer_kind () + == TyTy::InferType::InferTypeKind::INTEGRAL); + if (is_valid) + { + resolved = type.clone (); + return; + } + + BaseRules::visit (type); + } + + void visit (ISizeType &type) override + { + bool is_valid + = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) + || (base->get_infer_kind () + == TyTy::InferType::InferTypeKind::INTEGRAL); + if (is_valid) + { + resolved = type.clone (); + return; + } + + BaseRules::visit (type); + } + void visit (FloatType &type) override { bool is_valid @@ -591,6 +635,54 @@ private: TupleType *base; }; +class USizeRules : public BaseRules +{ +public: + USizeRules (USizeType *base) : BaseRules (base), base (base) {} + + void visit (InferType &type) override + { + // cant assign a float inference variable + if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) + { + BaseRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); + } + + void visit (USizeType &type) override { resolved = type.clone (); } + +private: + USizeType *base; +}; + +class ISizeRules : public BaseRules +{ +public: + ISizeRules (ISizeType *base) : BaseRules (base), base (base) {} + + void visit (InferType &type) override + { + // cant assign a float inference variable + if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) + { + BaseRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); + } + + void visit (ISizeType &type) override { resolved = type.clone (); } + +private: + ISizeType *base; +}; + } // namespace TyTy } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h index 3997295..6ae0e80 100644 --- a/gcc/rust/typecheck/rust-tyty-visitor.h +++ b/gcc/rust/typecheck/rust-tyty-visitor.h @@ -38,6 +38,8 @@ public: virtual void visit (IntType &type) = 0; virtual void visit (UintType &type) = 0; virtual void visit (FloatType &type) = 0; + virtual void visit (USizeType &type) = 0; + virtual void visit (ISizeType &type) = 0; virtual void visit (ErrorType &type) = 0; }; diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 9efde68..249e876 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -432,6 +432,56 @@ FloatType::clone () } void +USizeType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +USizeType::as_string () const +{ + return "usize"; +} + +TyBase * +USizeType::combine (TyBase *other) +{ + USizeRules r (this); + return r.combine (other); +} + +TyBase * +USizeType::clone () +{ + return new USizeType (get_ref (), get_ty_ref (), get_combined_refs ()); +} + +void +ISizeType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +ISizeType::as_string () const +{ + return "isize"; +} + +TyBase * +ISizeType::combine (TyBase *other) +{ + ISizeRules r (this); + return r.combine (other); +} + +TyBase * +ISizeType::clone () +{ + return new ISizeType (get_ref (), get_ty_ref (), get_combined_refs ()); +} + +void TypeCheckCallExpr::visit (ADTType &type) { if (call.num_params () != type.num_fields ()) diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 6c6f27c..860ef96 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -43,6 +43,8 @@ enum TypeKind FLOAT, UNIT, FIELD, + USIZE, + ISIZE, // there are more to add... ERROR }; @@ -510,6 +512,46 @@ private: FloatKind float_kind; }; +class USizeType : public TyBase +{ +public: + USizeType (HirId ref, std::set refs = std::set ()) + : TyBase (ref, ref, TypeKind::USIZE) + {} + + USizeType (HirId ref, HirId ty_ref, std::set refs = std::set ()) + : TyBase (ref, ty_ref, TypeKind::USIZE) + {} + + void accept_vis (TyVisitor &vis) override; + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; + + TyBase *clone () final override; +}; + +class ISizeType : public TyBase +{ +public: + ISizeType (HirId ref, std::set refs = std::set ()) + : TyBase (ref, ref, TypeKind::ISIZE) + {} + + ISizeType (HirId ref, HirId ty_ref, std::set refs = std::set ()) + : TyBase (ref, ty_ref, TypeKind::ISIZE) + {} + + void accept_vis (TyVisitor &vis) override; + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; + + TyBase *clone () final override; +}; + } // namespace TyTy } // namespace Rust -- cgit v1.1 From 8578c61be5061fab91fe679a15fd68ab5fad987c Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 25 Jan 2021 17:03:36 +0000 Subject: Add mutablity checks and left hand size assignee checker In order to assign to a name we must ensure the LHS is a valid expression to assign to. This leads onto actually checking if this is a mutable declaration or not. Once these checks pass the name resolver we can in GIMPLE create immutable types for these declarations to help with optimization. Fixes #77 --- gcc/rust/ast/rust-ast.h | 2 +- gcc/rust/backend/rust-compile-fnparam.h | 67 ++++++++++++++++++++++ gcc/rust/backend/rust-compile-item.h | 18 +++--- gcc/rust/backend/rust-compile-var-decl.h | 3 + gcc/rust/resolve/rust-ast-resolve-expr.h | 7 +++ gcc/rust/resolve/rust-ast-resolve-item.h | 15 +++++ gcc/rust/resolve/rust-ast-resolve-pattern.h | 2 + gcc/rust/resolve/rust-ast-resolve-stmt.h | 8 ++- gcc/rust/resolve/rust-ast-resolve-toplevel.h | 1 + gcc/rust/resolve/rust-ast-verify-assignee.h | 83 ++++++++++++++++++++++++++++ gcc/rust/resolve/rust-name-resolver.h | 36 ++++++++++++ 11 files changed, 233 insertions(+), 9 deletions(-) create mode 100644 gcc/rust/backend/rust-compile-fnparam.h create mode 100644 gcc/rust/resolve/rust-ast-verify-assignee.h (limited to 'gcc/rust') diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 34122bb..7b325830 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -962,7 +962,7 @@ public: std::string as_string () const override { return ident; } Location get_locus () const { return locus; } - Location get_locus_slow () const override { return get_locus (); } + Location get_locus_slow () const override { return locus; } Identifier get_ident () const { return ident; } diff --git a/gcc/rust/backend/rust-compile-fnparam.h b/gcc/rust/backend/rust-compile-fnparam.h new file mode 100644 index 0000000..cf6e6f7 --- /dev/null +++ b/gcc/rust/backend/rust-compile-fnparam.h @@ -0,0 +1,67 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#ifndef RUST_COMPILE_FNPARAM +#define RUST_COMPILE_FNPARAM + +#include "rust-compile-base.h" + +namespace Rust { +namespace Compile { + +class CompileFnParam : public HIRCompileBase +{ +public: + static Bvariable *compile (Context *ctx, Bfunction *fndecl, + HIR::FunctionParam *param, Btype *decl_type, + Location locus) + { + CompileFnParam compiler (ctx, fndecl, decl_type, locus); + param->get_param_name ()->accept_vis (compiler); + return compiler.translated; + } + + void visit (HIR::IdentifierPattern &pattern) + { + if (!pattern.is_mut) + decl_type = ctx->get_backend ()->immutable_type (decl_type); + + translated + = ctx->get_backend ()->parameter_variable (fndecl, pattern.variable_ident, + decl_type, + false /* address_taken */, + locus); + } + +private: + CompileFnParam (Context *ctx, ::Bfunction *fndecl, ::Btype *decl_type, + Location locus) + : HIRCompileBase (ctx), fndecl (fndecl), decl_type (decl_type), + locus (locus), translated (nullptr) + {} + + ::Bfunction *fndecl; + ::Btype *decl_type; + Location locus; + ::Bvariable *translated; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_FNPARAM diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index bf899d8..1bb7c91 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -24,6 +24,7 @@ #include "rust-compile-var-decl.h" #include "rust-compile-stmt.h" #include "rust-compile-expr.h" +#include "rust-compile-fnparam.h" namespace Rust { namespace Compile { @@ -174,17 +175,20 @@ public: for (auto &it : fntype->get_params ()) { HIR::FunctionParam &referenced_param = function.function_params.at (i); - auto param_pattern = it.first; auto param_tyty = it.second; - auto compiled_param_type = TyTyResolveCompile::compile (ctx, param_tyty); - bool tree_addressable = false; - auto compiled_param_var = ctx->get_backend ()->parameter_variable ( - fndecl, param_pattern->as_string (), compiled_param_type, - tree_addressable, - ctx->get_mappings ()->lookup_location (param_tyty->get_ref ())); + Location param_locus + = ctx->get_mappings ()->lookup_location (param_tyty->get_ref ()); + Bvariable *compiled_param_var + = CompileFnParam::compile (ctx, fndecl, &referenced_param, + compiled_param_type, param_locus); + if (compiled_param_var == nullptr) + { + rust_error_at (param_locus, "failed to compile parameter variable"); + return; + } param_vars.push_back (compiled_param_var); diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h index cf73820..06ea5a9 100644 --- a/gcc/rust/backend/rust-compile-var-decl.h +++ b/gcc/rust/backend/rust-compile-var-decl.h @@ -54,6 +54,9 @@ public: void visit (HIR::IdentifierPattern &pattern) { + if (!pattern.is_mut) + translated_type = ctx->get_backend ()->immutable_type (translated_type); + translated = ctx->get_backend ()->local_variable (fndecl, pattern.variable_ident, translated_type, NULL /*decl_var*/, diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 229b26a..9366818 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -22,6 +22,7 @@ #include "rust-ast-resolve-base.h" #include "rust-ast-full.h" #include "rust-ast-resolve-struct-expr-field.h" +#include "rust-ast-verify-assignee.h" namespace Rust { namespace Resolver { @@ -94,6 +95,9 @@ public: { ResolveExpr::go (expr.get_left_expr ().get (), expr.get_node_id ()); ResolveExpr::go (expr.get_right_expr ().get (), expr.get_node_id ()); + + // need to verify the assignee + VerifyAsignee::go (expr.get_left_expr ().get (), expr.get_node_id ()); } void visit (AST::IdentifierExpr &expr) @@ -120,6 +124,9 @@ public: { ResolveExpr::go (expr.get_left_expr ().get (), expr.get_node_id ()); ResolveExpr::go (expr.get_right_expr ().get (), expr.get_node_id ()); + + // need to verify the assignee + VerifyAsignee::go (expr.get_left_expr ().get (), expr.get_node_id ()); } void visit (AST::ComparisonExpr &expr) diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index 02d6dfa..0f45ba0 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -62,12 +62,22 @@ public: { ResolveType::go (var.get_type ().get (), var.get_node_id ()); ResolveExpr::go (var.get_expr ().get (), var.get_node_id ()); + + // the mutability checker needs to verify for immutable decls the number + // of assignments are <1. This marks an implicit assignment + resolver->mark_assignment_to_decl (var.get_node_id (), var.get_node_id ()); } void visit (AST::ConstantItem &constant) { ResolveType::go (constant.get_type ().get (), constant.get_node_id ()); ResolveExpr::go (constant.get_expr ().get (), constant.get_node_id ()); + + // the mutability checker needs to verify for immutable decls the number + // of assignments are <1. This marks an implicit assignment + resolver->mark_decl_mutability (constant.get_node_id (), false); + resolver->mark_assignment_to_decl (constant.get_node_id (), + constant.get_node_id ()); } void visit (AST::Function &function) @@ -89,6 +99,11 @@ public: ResolveType::go (param.get_type ().get (), param.get_node_id ()); PatternDeclaration::go (param.get_pattern ().get (), param.get_node_id ()); + + // the mutability checker needs to verify for immutable decls the number + // of assignments are <1. This marks an implicit assignment + resolver->mark_assignment_to_decl (param.get_pattern ()->get_node_id (), + param.get_node_id ()); } // resolve the function body diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h index c79f7d3..f7618ab 100644 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.h +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.h @@ -86,6 +86,8 @@ public: resolver->insert_new_definition (pattern.get_node_id (), Definition{pattern.get_node_id (), parent}); + resolver->mark_decl_mutability (pattern.get_node_id (), + pattern.get_is_mut ()); } private: diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h index 6d751e6..8904ce9 100644 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h @@ -52,7 +52,13 @@ public: void visit (AST::LetStmt &stmt) { if (stmt.has_init_expr ()) - ResolveExpr::go (stmt.get_init_expr ().get (), stmt.get_node_id ()); + { + ResolveExpr::go (stmt.get_init_expr ().get (), stmt.get_node_id ()); + + // mark the assignment + resolver->mark_assignment_to_decl (stmt.get_pattern ()->get_node_id (), + stmt.get_node_id ()); + } PatternDeclaration::go (stmt.get_pattern ().get (), stmt.get_node_id ()); if (stmt.has_type ()) diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h index 47435a7..90f9cd6 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -57,6 +57,7 @@ public: resolver->insert_new_definition (var.get_node_id (), Definition{var.get_node_id (), var.get_node_id ()}); + resolver->mark_decl_mutability (var.get_node_id (), var.is_mutable ()); } void visit (AST::ConstantItem &constant) diff --git a/gcc/rust/resolve/rust-ast-verify-assignee.h b/gcc/rust/resolve/rust-ast-verify-assignee.h new file mode 100644 index 0000000..6cfe2c2 --- /dev/null +++ b/gcc/rust/resolve/rust-ast-verify-assignee.h @@ -0,0 +1,83 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#ifndef RUST_AST_VERIFY_ASSIGNEE +#define RUST_AST_VERIFY_ASSIGNEE + +#include "rust-ast-resolve-base.h" +#include "rust-ast-full.h" + +namespace Rust { +namespace Resolver { + +class VerifyAsignee : public ResolverBase +{ +public: + static bool go (AST::Expr *assignee, NodeId parent) + { + VerifyAsignee checker (parent); + assignee->accept_vis (checker); + if (!checker.ok) + rust_error_at (assignee->get_locus_slow (), + "invalid left-hand side of assignment"); + return checker.ok; + } + + void visit (AST::ArrayIndexExpr &expr) + { + expr.get_array_expr ()->accept_vis (*this); + } + + void visit (AST::FieldAccessExpr &expr) + { + expr.get_receiver_expr ()->accept_vis (*this); + } + + void visit (AST::TupleIndexExpr &expr) + { + expr.get_tuple_expr ()->accept_vis (*this); + } + + void visit (AST::IdentifierExpr &expr) + { + if (!resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node)) + return; + + ok = true; + // mark the assignment to the name + resolver->mark_assignment_to_decl (resolved_node, parent); + + // check is mutable + if (!resolver->decl_is_mutable (resolved_node)) + { + // we only allow a single assignment to immutable decls + if (resolver->get_num_assignments_to_decl (resolved_node) > 1) + rust_error_at (expr.get_locus (), "cannot assign to immutable"); + } + } + +private: + VerifyAsignee (NodeId parent) : ResolverBase (parent), ok (false) {} + + bool ok; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_VERIFY_ASSIGNEE diff --git a/gcc/rust/resolve/rust-name-resolver.h b/gcc/rust/resolve/rust-name-resolver.h index 4d98e7f..5bc6aba 100644 --- a/gcc/rust/resolve/rust-name-resolver.h +++ b/gcc/rust/resolve/rust-name-resolver.h @@ -235,6 +235,37 @@ public: void set_unit_type_node_id (NodeId id) { unit_ty_node_id = id; } NodeId get_unit_type_node_id () { return unit_ty_node_id; } + void mark_decl_mutability (NodeId id, bool mut) + { + rust_assert (decl_mutability.find (id) == decl_mutability.end ()); + decl_mutability[id] = mut; + } + + bool decl_is_mutable (NodeId id) const + { + auto it = decl_mutability.find (id); + rust_assert (it != decl_mutability.end ()); + return it->second; + } + + void mark_assignment_to_decl (NodeId id, NodeId assignment) + { + auto it = assignment_to_decl.find (id); + if (it == assignment_to_decl.end ()) + assignment_to_decl[id] = {}; + + assignment_to_decl[id].insert (assignment); + } + + size_t get_num_assignments_to_decl (NodeId id) const + { + auto it = assignment_to_decl.find (id); + if (it == assignment_to_decl.end ()) + return 0; + + return it->second.size (); + } + private: Resolver (); @@ -269,6 +300,11 @@ private: // we need two namespaces one for names and ones for types std::map resolved_names; std::map resolved_types; + + // map of resolved names mutability flag + std::map decl_mutability; + // map of resolved names and set of assignments to the decl + std::map > assignment_to_decl; }; } // namespace Resolver -- cgit v1.1 From 244c2d2ea1a5a69ab6f7f50902512c1a7daa29c9 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 26 Jan 2021 17:28:52 +0000 Subject: Support binding functions to LetStmts. This supports basic function pointers in rust most of the code was already there to infer this but this has now helped tidy it up and make it work. Fixes #184 --- gcc/rust/ast/rust-type.h | 4 ++ gcc/rust/backend/rust-compile-expr.h | 28 +++++++++----- gcc/rust/backend/rust-compile-resolve-path.cc | 32 ++++++++++++--- gcc/rust/hir/rust-ast-lower-type.h | 51 ++++++++++++++++++++++++ gcc/rust/hir/tree/rust-hir-type.h | 34 ++++++++++++---- gcc/rust/resolve/rust-ast-resolve-expr.h | 22 ++++++++--- gcc/rust/resolve/rust-ast-resolve-toplevel.h | 3 ++ gcc/rust/resolve/rust-ast-resolve-type.h | 9 +++++ gcc/rust/rust-session-manager.cc | 4 +- gcc/rust/typecheck/rust-hir-type-check-expr.h | 56 ++++++++++++++++++++------- gcc/rust/typecheck/rust-hir-type-check-type.h | 28 ++++++++++++++ gcc/rust/typecheck/rust-tyty-rules.h | 46 ++++++++++++++++++++++ gcc/rust/typecheck/rust-tyty.cc | 7 +++- 13 files changed, 276 insertions(+), 48 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index 0dfeb07..a9e0f0f 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -816,6 +816,10 @@ public: rust_assert (param_type != nullptr); return param_type; } + + ParamKind get_param_kind () const { return param_kind; } + + Identifier get_name () const { return name; } }; /* A function pointer type - can be created via coercion from function items and diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 7c2f32d..81d7786 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -127,20 +127,28 @@ public: return; } - // this could be a constant reference - if (ctx->lookup_const_decl (ref, &translated)) - return; - - // must be an identifier + Bfunction *fn = nullptr; Bvariable *var = nullptr; - if (!ctx->lookup_var_decl (ref, &var)) + if (ctx->lookup_const_decl (ref, &translated)) { - rust_fatal_error (expr.get_locus (), - "failed to lookup compiled variable"); return; } - - translated = ctx->get_backend ()->var_expression (var, expr.get_locus ()); + else if (ctx->lookup_function_decl (ref, &fn)) + { + translated + = ctx->get_backend ()->function_code_expression (fn, + expr.get_locus ()); + } + else if (ctx->lookup_var_decl (ref, &var)) + { + translated + = ctx->get_backend ()->var_expression (var, expr.get_locus ()); + } + else + { + rust_fatal_error (expr.get_locus (), + "failed to lookup compiled reference"); + } } void visit (HIR::LiteralExpr &expr) diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index 37285b7..818d5cb 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -28,23 +28,43 @@ void ResolvePathRef::visit (HIR::PathInExpression &expr) { // need to look up the reference for this identifier - NodeId ref_node_id; - if (!ctx->get_resolver ()->lookup_resolved_name ( + NodeId ref_node_id = UNKNOWN_NODEID; + if (ctx->get_resolver ()->lookup_resolved_name ( expr.get_mappings ().get_nodeid (), &ref_node_id)) { - return; + Resolver::Definition def; + if (!ctx->get_resolver ()->lookup_definition (ref_node_id, &def)) + { + rust_error_at (expr.get_locus (), + "unknown reference for resolved name"); + return; + } + ref_node_id = def.parent; } + // this can fail because it might be a Constructor for something + // in that case the caller should attempt ResolvePathType::Compile + if (ref_node_id == UNKNOWN_NODEID) + return; + HirId ref; if (!ctx->get_mappings ()->lookup_node_to_hir ( expr.get_mappings ().get_crate_num (), ref_node_id, &ref)) { - rust_error_at (expr.get_locus (), "reverse lookup failure"); + rust_error_at (expr.get_locus (), "reverse call path lookup failure"); return; } - // assumes paths are functions for now - Bfunction *fn; + // this might be a variable reference or a function reference + Bvariable *var = nullptr; + if (ctx->lookup_var_decl (ref, &var)) + { + resolved = ctx->get_backend ()->var_expression (var, expr.get_locus ()); + return; + } + + // must be a function call + Bfunction *fn = nullptr; if (!ctx->lookup_function_decl (ref, &fn)) { // this might fail because its a forward decl so we can attempt to diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index 84d09bc..e78ae5a 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -42,6 +42,57 @@ public: return resolver.translated; } + void visit (AST::BareFunctionType &fntype) + { + bool is_variadic = false; + std::vector lifetime_params; + HIR::FunctionQualifiers qualifiers ( + HIR::FunctionQualifiers::AsyncConstStatus::NONE, false); + + std::vector named_params; + for (auto ¶m : fntype.get_function_params ()) + { + HIR::MaybeNamedParam::ParamKind kind; + switch (param.get_param_kind ()) + { + case AST::MaybeNamedParam::ParamKind::UNNAMED: + kind = HIR::MaybeNamedParam::ParamKind::UNNAMED; + break; + case AST::MaybeNamedParam::ParamKind::IDENTIFIER: + kind = HIR::MaybeNamedParam::ParamKind::IDENTIFIER; + break; + case AST::MaybeNamedParam::ParamKind::WILDCARD: + kind = HIR::MaybeNamedParam::ParamKind::WILDCARD; + break; + } + + HIR::Type *param_type + = ASTLoweringType::translate (param.get_type ().get ()); + + HIR::MaybeNamedParam p (param.get_name (), kind, + std::unique_ptr (param_type), + param.get_locus ()); + named_params.push_back (std::move (p)); + } + + HIR::Type *return_type = nullptr; + if (fntype.has_return_type ()) + { + return_type + = ASTLoweringType::translate (fntype.get_return_type ().get ()); + } + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, fntype.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + + translated = new HIR::BareFunctionType ( + std::move (mapping), std::move (lifetime_params), std::move (qualifiers), + std::move (named_params), is_variadic, + std::unique_ptr (return_type), fntype.get_locus ()); + } + void visit (AST::TupleType &tuple) { std::vector > elems; diff --git a/gcc/rust/hir/tree/rust-hir-type.h b/gcc/rust/hir/tree/rust-hir-type.h index fc369c3..ebed119 100644 --- a/gcc/rust/hir/tree/rust-hir-type.h +++ b/gcc/rust/hir/tree/rust-hir-type.h @@ -791,6 +791,16 @@ public: } Location get_locus () const { return locus; } + + std::unique_ptr &get_type () + { + rust_assert (param_type != nullptr); + return param_type; + } + + ParamKind get_param_kind () const { return param_kind; } + + Identifier get_name () const { return name; } }; /* A function pointer type - can be created via coercion from function items and @@ -805,9 +815,7 @@ class BareFunctionType : public TypeNoBounds std::vector params; bool is_variadic; - // bool has_return_type; - // BareFunctionReturnType return_type; - std::unique_ptr return_type; // inlined version + std::unique_ptr return_type; // inlined version Location locus; @@ -822,7 +830,7 @@ public: std::vector lifetime_params, FunctionQualifiers qualifiers, std::vector named_params, bool is_variadic, - std::unique_ptr type, Location locus) + std::unique_ptr type, Location locus) : TypeNoBounds (mappings), for_lifetimes (std::move (lifetime_params)), function_qualifiers (std::move (qualifiers)), params (std::move (named_params)), is_variadic (is_variadic), @@ -834,8 +842,7 @@ public: : TypeNoBounds (other.mappings), for_lifetimes (other.for_lifetimes), function_qualifiers (other.function_qualifiers), params (other.params), is_variadic (other.is_variadic), - return_type (other.return_type->clone_type_no_bounds ()), - locus (other.locus) + return_type (other.return_type->clone_type ()), locus (other.locus) {} // Overload assignment operator to deep copy @@ -846,7 +853,7 @@ public: function_qualifiers = other.function_qualifiers; params = other.params; is_variadic = other.is_variadic; - return_type = other.return_type->clone_type_no_bounds (); + return_type = other.return_type->clone_type (); locus = other.locus; return *this; @@ -862,6 +869,19 @@ public: void accept_vis (HIRVisitor &vis) override; + std::vector &get_function_params () { return params; } + const std::vector &get_function_params () const + { + return params; + } + + // TODO: would a "vis_type" be better? + std::unique_ptr &get_return_type () + { + rust_assert (has_return_type ()); + return return_type; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 9366818..f62f17c 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -102,16 +102,26 @@ public: void visit (AST::IdentifierExpr &expr) { - if (!resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node)) + if (resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node)) + { + resolver->insert_resolved_name (expr.get_node_id (), resolved_node); + resolver->insert_new_definition (expr.get_node_id (), + Definition{expr.get_node_id (), + parent}); + } + else if (resolver->get_type_scope ().lookup (expr.as_string (), + &resolved_node)) + { + resolver->insert_resolved_type (expr.get_node_id (), resolved_node); + resolver->insert_new_definition (expr.get_node_id (), + Definition{expr.get_node_id (), + parent}); + } + else { rust_error_at (expr.get_locus (), "failed to find name: %s", expr.as_string ().c_str ()); - return; } - - resolver->insert_resolved_name (expr.get_node_id (), resolved_node); - resolver->insert_new_definition (expr.get_node_id (), - Definition{expr.get_node_id (), parent}); } void visit (AST::ArithmeticOrLogicalExpr &expr) diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h index 90f9cd6..c3f5e4c 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -75,6 +75,9 @@ public: resolver->get_name_scope ().insert (function.get_function_name (), function.get_node_id (), function.get_locus ()); + resolver->insert_new_definition (function.get_node_id (), + Definition{function.get_node_id (), + function.get_node_id ()}); // if this does not get a reference it will be determined to be unused // lets give it a fake reference to itself diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index 20fb0b6..b303ee9 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -34,6 +34,15 @@ public: type->accept_vis (resolver); }; + void visit (AST::BareFunctionType &fntype) + { + for (auto ¶m : fntype.get_function_params ()) + ResolveType::go (param.get_type ().get (), fntype.get_node_id ()); + + if (fntype.has_return_type ()) + ResolveType::go (fntype.get_return_type ().get (), fntype.get_node_id ()); + } + void visit (AST::TupleType &tuple) { if (tuple.is_unit_type ()) diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 281049d..afc238b 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -550,8 +550,8 @@ Session::parse_file (const char *filename) type_resolution (hir); // FIXME this needs an option of itself - // auto buf = Resolver::TypeResolverDump::go (hir); - // fprintf (stderr, "%s\n", buf.c_str ()); + auto buf = Resolver::TypeResolverDump::go (hir); + fprintf (stderr, "%s\n", buf.c_str ()); if (saw_errors ()) return; diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 17f1611..78f0d0d 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -157,17 +157,32 @@ public: auto fn = expr.get_fnexpr (); auto fn_node_id = fn->get_mappings ().get_nodeid (); - // CallExpr might be a function but it might also be a TupleStruct - NodeId ref_node_id; - if (!resolver->lookup_resolved_name (fn_node_id, &ref_node_id)) + // then lookup the reference_node_id + NodeId ref_node_id = UNKNOWN_NODEID; + if (resolver->lookup_resolved_name (fn_node_id, &ref_node_id)) { - if (!resolver->lookup_resolved_type (fn_node_id, &ref_node_id)) + Definition def; + if (!resolver->lookup_definition (ref_node_id, &def)) { rust_error_at (expr.get_locus (), - "Failed to lookup reference for node: %s", - expr.as_string ().c_str ()); + "unknown reference for resolved name"); return; } + ref_node_id = def.parent; + } + else if (!resolver->lookup_resolved_type (fn_node_id, &ref_node_id)) + { + rust_error_at (expr.get_locus (), + "Failed to lookup type reference for node: %s", + expr.as_string ().c_str ()); + return; + } + + if (ref_node_id == UNKNOWN_NODEID) + { + rust_error_at (expr.get_locus (), "unresolved node: %s", + expr.as_string ().c_str ()); + return; } // node back to HIR @@ -258,28 +273,39 @@ public: NodeId ast_node_id = expr.get_mappings ().get_nodeid (); // then lookup the reference_node_id - NodeId ref_node_id; - if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + NodeId ref_node_id = UNKNOWN_NODEID; + if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + { + // these ref_node_ids will resolve to a pattern declaration but we are + // interested in the definition that this refers to get the parent id + Definition def; + if (!resolver->lookup_definition (ref_node_id, &def)) + { + rust_error_at (expr.get_locus (), + "unknown reference for resolved name"); + return; + } + ref_node_id = def.parent; + } + else if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id)) { rust_error_at (expr.get_locus (), - "Failed to lookup reference for node: %s", + "Failed to lookup type reference for node: %s", expr.as_string ().c_str ()); return; } - // these ref_node_ids will resolve to a pattern declaration but we are - // interested in the definition that this refers to get the parent id - Definition def; - if (!resolver->lookup_definition (ref_node_id, &def)) + if (ref_node_id == UNKNOWN_NODEID) { - rust_error_at (expr.get_locus (), "unknown reference"); + rust_error_at (expr.get_locus (), "unresolved node: %s", + expr.as_string ().c_str ()); return; } // node back to HIR HirId ref; if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (), - def.parent, &ref)) + ref_node_id, &ref)) { rust_error_at (expr.get_locus (), "reverse lookup failure"); return; diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index e5d3898..2894899 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -79,6 +79,34 @@ public: return resolver.translated; } + void visit (HIR::BareFunctionType &fntype) + { + TyTy::TyBase *return_type + = fntype.has_return_type () + ? TypeCheckType::Resolve (fntype.get_return_type ().get ()) + : new TyTy::UnitType (fntype.get_mappings ().get_hirid ()); + + std::vector > params; + for (auto ¶m : fntype.get_function_params ()) + { + std::unique_ptr to_bind; + + bool is_ref = false; + bool is_mut = false; + + HIR::Pattern *pattern + = new HIR::IdentifierPattern (param.get_name (), param.get_locus (), + is_ref, is_mut, std::move (to_bind)); + + TyTy::TyBase *ptype = TypeCheckType::Resolve (param.get_type ().get ()); + params.push_back ( + std::pair (pattern, ptype)); + } + + translated = new TyTy::FnType (fntype.get_mappings ().get_hirid (), + std::move (params), return_type); + } + void visit (HIR::TupleType &tuple) { if (tuple.is_unit_type ()) diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index e17cec7..be58805 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -410,6 +410,52 @@ class FnRules : public BaseRules public: FnRules (FnType *base) : BaseRules (base), base (base) {} + void visit (InferType &type) override + { + if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) + { + BaseRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); + } + + void visit (FnType &type) override + { + if (base->num_params () != type.num_params ()) + { + BaseRules::visit (type); + return; + } + + // FIXME add an abstract method for is_equal on TyBase + for (size_t i = 0; i < base->num_params (); i++) + { + auto a = base->param_at (i).second; + auto b = type.param_at (i).second; + + auto combined_param = a->combine (b); + if (combined_param == nullptr) + { + BaseRules::visit (type); + return; + } + } + + auto combined_return + = base->get_return_type ()->combine (type.get_return_type ()); + if (combined_return == nullptr) + { + BaseRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); + } + private: FnType *base; }; diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 249e876..d506415 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -147,11 +147,14 @@ ADTType::accept_vis (TyVisitor &vis) std::string ADTType::as_string () const { + if (num_fields () == 0) + return identifier; + std::string fields_buffer; for (auto &field : fields) - fields_buffer += field->as_string () + "\n"; + fields_buffer += field->as_string () + ", "; - return identifier + "{\n" + fields_buffer + "\n}"; + return identifier + "{" + fields_buffer + "}"; } TyBase * -- cgit v1.1