From 290fc4f416c94a86aa5e3d22b785890a12686972 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 6 Jan 2021 14:53:35 +0000 Subject: Add test to cover handling hex, binary and octal number literals. This also ensure the type suffix is respected against the number. --- gcc/rust/backend/rust-compile-tyty.h | 6 +++--- gcc/testsuite/rust.test/compilable/literals1.rs | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/rust.test/compilable/literals1.rs (limited to 'gcc') diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index 528f90e..2d4e1f0 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -132,19 +132,19 @@ public: switch (type.get_kind ()) { case TyTy::UintType::U8: - translated = backend->named_type ("i8", backend->integer_type (true, 8), + translated = backend->named_type ("u8", backend->integer_type (true, 8), Linemap::predeclared_location ()); return; case TyTy::UintType::U16: translated - = backend->named_type ("i16", backend->integer_type (true, 16), + = backend->named_type ("u16", backend->integer_type (true, 16), Linemap::predeclared_location ()); return; case TyTy::UintType::U32: translated - = backend->named_type ("i32", backend->integer_type (true, 32), + = backend->named_type ("u32", backend->integer_type (true, 32), Linemap::predeclared_location ()); return; diff --git a/gcc/testsuite/rust.test/compilable/literals1.rs b/gcc/testsuite/rust.test/compilable/literals1.rs new file mode 100644 index 0000000..cd48e83 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/literals1.rs @@ -0,0 +1,9 @@ +fn main() { + let hex: i32 = 0xFF; + let binary: i32 = 0b11110000; + let oct: i32 = 0o70; + + let hex_u8: u8 = 0xFF_u8; + let bin_u16: u16 = 0b1111000011110000_u16; + let oct: u32 = 0o70_u32; +} -- cgit v1.1 From 4e0189ed288223f8b376eedd286f5bdff5b35698 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 6 Jan 2021 18:18:42 +0000 Subject: Implicit Returns support. For implict returns we must consider cases with a block having multiple returns: HIR::BlockExpr Stmts { ... return x } HIR::BlockExpr final_expression { x + 1 } Although the code above is bad this is valid rust code and the rust compiler correctly identifies the final_expression as unreachable. This dead code eliminiation is done as part of AST to HIR lowering. Type resolution examines all blocks to identifiy if they terminate a function with a return/final expression it must correspond accordngly. If the block is the final block the resulting termination of the block must match the return type of the function, else the block must conform to unit type. --- gcc/rust/ast/rust-expr.h | 2 + gcc/rust/ast/rust-stmt.h | 2 + gcc/rust/backend/rust-compile-item.h | 17 +++++ gcc/rust/backend/rust-compile.cc | 17 +++++ gcc/rust/hir/rust-ast-lower-block.h | 32 ++++++--- gcc/rust/hir/rust-ast-lower-expr.h | 23 +++++-- gcc/rust/hir/rust-ast-lower-item.h | 7 +- gcc/rust/hir/rust-ast-lower-stmt.h | 18 ++--- gcc/rust/hir/rust-ast-lower.cc | 67 +++++++++++++++--- gcc/rust/hir/tree/rust-hir-expr.h | 2 + gcc/rust/resolve/rust-ast-resolve-item.h | 4 ++ gcc/rust/typecheck/rust-hir-type-check-expr.h | 48 ++++++++++--- gcc/rust/typecheck/rust-hir-type-check-item.h | 20 +----- gcc/rust/typecheck/rust-hir-type-check-stmt.h | 19 +++-- gcc/rust/typecheck/rust-hir-type-check.cc | 36 +++++++++- gcc/rust/typecheck/rust-tyty-resolver.h | 8 +-- gcc/rust/typecheck/rust-tyty-rules.h | 80 +++++++++++++++------- gcc/rust/typecheck/rust-tyty.h | 2 +- gcc/testsuite/rust.test/compilable/deadcode1.rs | 18 +++++ .../rust.test/compilable/implicit_returns1.rs | 65 ++++++++++++++++++ .../rust.test/fail_compilation/missing_return1.rs | 5 ++ 21 files changed, 387 insertions(+), 105 deletions(-) create mode 100644 gcc/testsuite/rust.test/compilable/deadcode1.rs create mode 100644 gcc/testsuite/rust.test/compilable/implicit_returns1.rs create mode 100644 gcc/testsuite/rust.test/fail_compilation/missing_return1.rs (limited to 'gcc') diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 8baf7b7..2dbaec8 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -2838,6 +2838,8 @@ public: } } + size_t num_statements () const { return statements.size (); } + // TODO: this mutable getter seems really dodgy. Think up better way. const std::vector &get_inner_attrs () const { return inner_attrs; } std::vector &get_inner_attrs () { return inner_attrs; } diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index c2ce387..c840112 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -184,6 +184,8 @@ class ExprStmt : public Stmt Location locus; public: + Location get_locus_slow () const final override { return get_locus (); } + Location get_locus () const { return locus; } protected: diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index 90630bb..f1b39da 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -232,6 +232,23 @@ public: return true; }); + if (function_body->has_expr ()) + { + // the previous passes will ensure this is a valid return + // dead code elimination should remove any bad trailing expressions + Bexpression *compiled_expr + = CompileExpr::Compile (function_body->expr.get (), ctx); + rust_assert (compiled_expr != nullptr); + + auto fncontext = ctx->peek_fn (); + + std::vector retstmts; + retstmts.push_back (compiled_expr); + auto s = ctx->get_backend ()->return_statement ( + fncontext.fndecl, retstmts, function_body->expr->get_locus_slow ()); + ctx->add_statement (s); + } + ctx->pop_block (); auto body = ctx->get_backend ()->block_statement (code_block); if (!ctx->get_backend ()->function_set_body (fndecl, body)) diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 24b45ee..a52f183 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -90,6 +90,23 @@ CompileBlock::visit (HIR::BlockExpr &expr) return true; }); + if (expr.has_expr ()) + { + // the previous passes will ensure this is a valid return + // dead code elimination should remove any bad trailing expressions + Bexpression *compiled_expr = CompileExpr::Compile (expr.expr.get (), ctx); + rust_assert (compiled_expr != nullptr); + + auto fncontext = ctx->peek_fn (); + + std::vector retstmts; + retstmts.push_back (compiled_expr); + auto s + = ctx->get_backend ()->return_statement (fncontext.fndecl, retstmts, + expr.expr->get_locus_slow ()); + ctx->add_statement (s); + } + ctx->pop_block (); translated = new_block; } diff --git a/gcc/rust/hir/rust-ast-lower-block.h b/gcc/rust/hir/rust-ast-lower-block.h index 11f1ab8..1ef581e 100644 --- a/gcc/rust/hir/rust-ast-lower-block.h +++ b/gcc/rust/hir/rust-ast-lower-block.h @@ -28,7 +28,7 @@ namespace HIR { class ASTLoweringBlock : public ASTLoweringBase { public: - static HIR::BlockExpr *translate (AST::BlockExpr *expr) + static HIR::BlockExpr *translate (AST::BlockExpr *expr, bool *terminated) { ASTLoweringBlock resolver; expr->accept_vis (resolver); @@ -40,6 +40,7 @@ public: resolver.translated); } + *terminated = resolver.terminated; return resolver.translated; } @@ -48,15 +49,18 @@ public: void visit (AST::BlockExpr &expr); private: - ASTLoweringBlock () : ASTLoweringBase (), translated (nullptr) {} + ASTLoweringBlock () + : ASTLoweringBase (), translated (nullptr), terminated (false) + {} HIR::BlockExpr *translated; + bool terminated; }; class ASTLoweringIfBlock : public ASTLoweringBase { public: - static HIR::IfExpr *translate (AST::IfExpr *expr) + static HIR::IfExpr *translate (AST::IfExpr *expr, bool *terminated) { ASTLoweringIfBlock resolver; expr->accept_vis (resolver); @@ -67,7 +71,7 @@ public: resolver.translated->get_mappings ().get_hirid (), resolver.translated); } - + *terminated = resolver.terminated; return resolver.translated; } @@ -80,15 +84,19 @@ public: void visit (AST::IfExprConseqIf &expr); private: - ASTLoweringIfBlock () : ASTLoweringBase (), translated (nullptr) {} + ASTLoweringIfBlock () + : ASTLoweringBase (), translated (nullptr), terminated (false) + {} HIR::IfExpr *translated; + bool terminated; }; class ASTLoweringExprWithBlock : public ASTLoweringBase { public: - static HIR::ExprWithBlock *translate (AST::ExprWithBlock *expr) + static HIR::ExprWithBlock *translate (AST::ExprWithBlock *expr, + bool *terminated) { ASTLoweringExprWithBlock resolver; expr->accept_vis (resolver); @@ -100,6 +108,7 @@ public: resolver.translated); } + *terminated = resolver.terminated; return resolver.translated; } @@ -107,23 +116,26 @@ public: void visit (AST::IfExpr &expr) { - translated = ASTLoweringIfBlock::translate (&expr); + translated = ASTLoweringIfBlock::translate (&expr, &terminated); } void visit (AST::IfExprConseqElse &expr) { - translated = ASTLoweringIfBlock::translate (&expr); + translated = ASTLoweringIfBlock::translate (&expr, &terminated); } void visit (AST::IfExprConseqIf &expr) { - translated = ASTLoweringIfBlock::translate (&expr); + translated = ASTLoweringIfBlock::translate (&expr, &terminated); } private: - ASTLoweringExprWithBlock () : ASTLoweringBase (), translated (nullptr) {} + ASTLoweringExprWithBlock () + : ASTLoweringBase (), translated (nullptr), terminated (false) + {} HIR::ExprWithBlock *translated; + bool terminated; }; } // namespace HIR diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index 87ba0dc..51bf108 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -107,7 +107,7 @@ private: class ASTLoweringExpr : public ASTLoweringBase { public: - static HIR::Expr *translate (AST::Expr *expr) + static HIR::Expr *translate (AST::Expr *expr, bool *terminated = nullptr) { ASTLoweringExpr resolver; expr->accept_vis (resolver); @@ -121,6 +121,13 @@ public: resolver.mappings->insert_hir_expr ( resolver.translated->get_mappings ().get_crate_num (), resolver.translated->get_mappings ().get_hirid (), resolver.translated); + resolver.mappings->insert_location ( + resolver.translated->get_mappings ().get_crate_num (), + resolver.translated->get_mappings ().get_hirid (), + expr->get_locus_slow ()); + + if (terminated != nullptr) + *terminated = resolver.terminated; return resolver.translated; } @@ -129,22 +136,22 @@ public: void visit (AST::IfExpr &expr) { - translated = ASTLoweringIfBlock::translate (&expr); + translated = ASTLoweringIfBlock::translate (&expr, &terminated); } void visit (AST::IfExprConseqElse &expr) { - translated = ASTLoweringIfBlock::translate (&expr); + translated = ASTLoweringIfBlock::translate (&expr, &terminated); } void visit (AST::IfExprConseqIf &expr) { - translated = ASTLoweringIfBlock::translate (&expr); + translated = ASTLoweringIfBlock::translate (&expr, &terminated); } void visit (AST::BlockExpr &expr) { - translated = ASTLoweringBlock::translate (&expr); + translated = ASTLoweringBlock::translate (&expr, &terminated); } void visit (AST::PathInExpression &expr) @@ -154,6 +161,7 @@ public: void visit (AST::ReturnExpr &expr) { + terminated = true; HIR::Expr *return_expr = expr.has_returned_expr () ? ASTLoweringExpr::translate (expr.get_returned_expr ().get ()) @@ -498,10 +506,13 @@ public: } private: - ASTLoweringExpr () : translated (nullptr), translated_array_elems (nullptr) {} + ASTLoweringExpr () + : translated (nullptr), translated_array_elems (nullptr), terminated (false) + {} HIR::Expr *translated; HIR::ArrayElems *translated_array_elems; + bool terminated; }; } // namespace HIR diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index 2a17880..4a5a3fe 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -185,9 +185,14 @@ public: function_params.push_back (hir_param); } + bool terminated = false; std::unique_ptr function_body = std::unique_ptr ( - ASTLoweringBlock::translate (function.get_definition ().get ())); + 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 (), diff --git a/gcc/rust/hir/rust-ast-lower-stmt.h b/gcc/rust/hir/rust-ast-lower-stmt.h index f4ecd8e..b672456 100644 --- a/gcc/rust/hir/rust-ast-lower-stmt.h +++ b/gcc/rust/hir/rust-ast-lower-stmt.h @@ -33,15 +33,12 @@ namespace HIR { class ASTLoweringStmt : public ASTLoweringBase { public: - static HIR::Stmt *translate (AST::Stmt *stmt) + static HIR::Stmt *translate (AST::Stmt *stmt, bool *terminated) { ASTLoweringStmt resolver; stmt->accept_vis (resolver); - if (resolver.translated == nullptr) - { - printf ("Failing translating: %s\n", stmt->as_string ().c_str ()); - rust_assert (resolver.translated != nullptr); - } + rust_assert (resolver.translated != nullptr); + *terminated = resolver.terminated; return resolver.translated; } @@ -50,7 +47,8 @@ public: void visit (AST::ExprStmtWithBlock &stmt) { HIR::ExprWithBlock *expr - = ASTLoweringExprWithBlock::translate (stmt.get_expr ().get ()); + = ASTLoweringExprWithBlock::translate (stmt.get_expr ().get (), + &terminated); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, stmt.get_node_id (), @@ -67,7 +65,8 @@ public: void visit (AST::ExprStmtWithoutBlock &stmt) { - HIR::Expr *expr = ASTLoweringExpr::translate (stmt.get_expr ().get ()); + HIR::Expr *expr + = ASTLoweringExpr::translate (stmt.get_expr ().get (), &terminated); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, stmt.get_node_id (), @@ -110,9 +109,10 @@ public: } private: - ASTLoweringStmt () : translated (nullptr) {} + ASTLoweringStmt () : translated (nullptr), terminated (false) {} HIR::Stmt *translated; + bool terminated; }; } // namespace HIR diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index 8dd8800..4f0d0d0 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -64,17 +64,44 @@ ASTLowering::go () void ASTLoweringBlock::visit (AST::BlockExpr &expr) { - std::vector > block_stmts; - std::unique_ptr block_expr; std::vector inner_attribs; std::vector outer_attribs; + std::vector > block_stmts; + bool block_did_terminate = false; expr.iterate_stmts ([&] (AST::Stmt *s) mutable -> bool { - auto translated_stmt = ASTLoweringStmt::translate (s); + bool terminated = false; + auto translated_stmt = ASTLoweringStmt::translate (s, &terminated); block_stmts.push_back (std::unique_ptr (translated_stmt)); + block_did_terminate = terminated; + return !block_did_terminate; + }); + + // if there was a return expression everything after that becomes + // unreachable code. This can be detected for any AST NodeIDs that have no + // associated HIR Mappings + expr.iterate_stmts ([&] (AST::Stmt *s) -> bool { + HirId ref; + if (!mappings->lookup_node_to_hir (mappings->get_current_crate (), + s->get_node_id (), &ref)) + rust_warning_at (s->get_locus_slow (), 0, "unreachable statement"); + 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) + { + // warning unreachable tail expressions + rust_warning_at (expr.get_tail_expr ()->get_locus_slow (), 0, + "unreachable expression"); + } + auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), @@ -82,17 +109,23 @@ ASTLoweringBlock::visit (AST::BlockExpr &expr) translated = new HIR::BlockExpr (mapping, std::move (block_stmts), - std::move (block_expr), std::move (inner_attribs), - std::move (outer_attribs), expr.get_locus ()); + std::unique_ptr (tail_expr), + std::move (inner_attribs), std::move (outer_attribs), + expr.get_locus ()); + + terminated = block_did_terminate || expr.has_tail_expr (); } void ASTLoweringIfBlock::visit (AST::IfExpr &expr) { + bool ignored_terminated = false; HIR::Expr *condition - = ASTLoweringExpr::translate (expr.get_condition_expr ().get ()); + = ASTLoweringExpr::translate (expr.get_condition_expr ().get (), + &ignored_terminated); HIR::BlockExpr *block - = ASTLoweringBlock::translate (expr.get_if_block ().get ()); + = ASTLoweringBlock::translate (expr.get_if_block ().get (), + &ignored_terminated); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), @@ -109,10 +142,18 @@ ASTLoweringIfBlock::visit (AST::IfExprConseqElse &expr) { HIR::Expr *condition = ASTLoweringExpr::translate (expr.get_condition_expr ().get ()); + + bool if_block_terminated = false; + bool else_block_termianted = false; + HIR::BlockExpr *if_block - = ASTLoweringBlock::translate (expr.get_if_block ().get ()); + = ASTLoweringBlock::translate (expr.get_if_block ().get (), + &if_block_terminated); HIR::BlockExpr *else_block - = ASTLoweringBlock::translate (expr.get_else_block ().get ()); + = ASTLoweringBlock::translate (expr.get_else_block ().get (), + &else_block_termianted); + + terminated = if_block_terminated && else_block_termianted; auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), @@ -132,10 +173,14 @@ ASTLoweringIfBlock::visit (AST::IfExprConseqIf &expr) { HIR::Expr *condition = ASTLoweringExpr::translate (expr.get_condition_expr ().get ()); + + bool ignored_terminated = false; HIR::BlockExpr *block - = ASTLoweringBlock::translate (expr.get_if_block ().get ()); + = ASTLoweringBlock::translate (expr.get_if_block ().get (), + &ignored_terminated); HIR::IfExpr *conseq_if_expr - = ASTLoweringIfBlock::translate (expr.get_conseq_if_expr ().get ()); + = ASTLoweringIfBlock::translate (expr.get_conseq_if_expr ().get (), + &ignored_terminated); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index dc7ab5a..11be8b6 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -2594,6 +2594,8 @@ public: } } + bool is_final_stmt (Stmt *stmt) { return statements.back ().get () == stmt; } + Location get_closing_locus () { if (statements.size () == 0) diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index c3b2312..c69e433 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -85,6 +85,10 @@ public: return true; }); + if (function.get_definition ()->has_tail_expr ()) + ResolveExpr::go (function.get_definition ()->get_tail_expr ().get (), + function.get_node_id ()); + resolver->get_name_scope ().pop (); resolver->get_type_scope ().pop (); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index a5440c0..29244a6 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -32,9 +32,9 @@ namespace Resolver { class TypeCheckExpr : public TypeCheckBase { public: - static TyTy::TyBase *Resolve (HIR::Expr *expr) + static TyTy::TyBase *Resolve (HIR::Expr *expr, bool is_final_expr = false) { - TypeCheckExpr resolver; + TypeCheckExpr resolver (is_final_expr); expr->accept_vis (resolver); if (resolver.infered != nullptr) resolver.context->insert_type (expr->get_mappings ().get_hirid (), @@ -245,13 +245,30 @@ public: { TypeCheckExpr::Resolve (expr.get_if_condition ()); TypeCheckExpr::Resolve (expr.get_if_block ()); + + // if without else always resolves to unit type + infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); } void visit (HIR::IfExprConseqElse &expr) { - TypeCheckExpr::Resolve (expr.get_if_condition ()); - TypeCheckExpr::Resolve (expr.get_if_block ()); - TypeCheckExpr::Resolve (expr.get_else_block ()); + // 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) + { + infered = infered->combine (if_blk_ty); + infered = infered->combine (else_blk_ty); + } } void visit (HIR::IfExprConseqIf &expr) @@ -259,22 +276,28 @@ public: TypeCheckExpr::Resolve (expr.get_if_condition ()); TypeCheckExpr::Resolve (expr.get_if_block ()); TypeCheckExpr::Resolve (expr.get_conseq_if_expr ()); + + infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); } void visit (HIR::BlockExpr &expr); void visit (HIR::ArrayIndexExpr &expr) { - // check the index + // 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 ())); - context->insert_type (expr.get_index_expr ()->get_mappings ().get_hirid (), - resolved); + rust_assert (resolved != nullptr); expr.get_array_expr ()->accept_vis (*this); - rust_assert (infered != nullptr); + if (infered->get_kind () != TyTy::TypeKind::ARRAY) + { + rust_fatal_error (expr.get_array_expr ()->get_locus_slow (), + "expected an ArrayType for index expression"); + return; + } // extract the element type out now from the base type infered = TyTyExtractorArray::ExtractElementTypeFromArray (infered); @@ -318,12 +341,15 @@ public: } private: - TypeCheckExpr () - : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr) + TypeCheckExpr (bool is_final_expr) + : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr), + is_final_expr (is_final_expr) {} TyTy::TyBase *infered; TyTy::TyBase *infered_array_elems; + + bool is_final_expr; }; } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index c90af13..adf842c 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -72,25 +72,7 @@ public: ResolveFnType resolve_fn_type (fnType); context->push_return_type (resolve_fn_type.go ()); - // walk statements to make sure they are all typed correctly and they match - // up - function.function_body->iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { - TypeCheckStmt::Resolve (s); - return true; - }); - - // 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 = function.function_body->get_mappings (); - Rib *rib = nullptr; - if (!resolver->find_name_rib (body_mappings.get_nodeid (), &rib)) - { - rust_fatal_error (function.get_locus (), - "failed to lookup locals per block"); - return; - } - - TyTyResolver::Resolve (rib, mappings, resolver, context); + TypeCheckExpr::Resolve (function.function_body.get ()); 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 dbf6583..bf754db 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -30,27 +30,29 @@ namespace Resolver { class TypeCheckStmt : public TypeCheckBase { public: - static void Resolve (HIR::Stmt *stmt) + static TyTy::TyBase *Resolve (HIR::Stmt *stmt, bool is_final_stmt) { - TypeCheckStmt resolver; + TypeCheckStmt resolver (is_final_stmt); stmt->accept_vis (resolver); + return resolver.infered; } void visit (HIR::ExprStmtWithBlock &stmt) { - TypeCheckExpr::Resolve (stmt.get_expr ()); + infered = TypeCheckExpr::Resolve (stmt.get_expr (), is_final_stmt); } void visit (HIR::ExprStmtWithoutBlock &stmt) { - TypeCheckExpr::Resolve (stmt.get_expr ()); + infered = TypeCheckExpr::Resolve (stmt.get_expr (), is_final_stmt); } void visit (HIR::LetStmt &stmt) { TyTy::TyBase *init_expr_ty = nullptr; if (stmt.has_init_expr ()) - init_expr_ty = TypeCheckExpr::Resolve (stmt.get_init_expr ()); + init_expr_ty + = TypeCheckExpr::Resolve (stmt.get_init_expr (), is_final_stmt); TyTy::TyBase *specified_ty = nullptr; if (stmt.has_type ()) @@ -94,7 +96,12 @@ public: } private: - TypeCheckStmt () : TypeCheckBase () {} + TypeCheckStmt (bool is_final_stmt) + : TypeCheckBase (), is_final_stmt (is_final_stmt) + {} + + TyTy::TyBase *infered; + bool is_final_stmt; }; // namespace Resolver } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index e7d3366..e68ba9a 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -40,10 +40,44 @@ TypeResolution::Resolve (HIR::Crate &crate) void TypeCheckExpr::visit (HIR::BlockExpr &expr) { + TyTy::TyBase *block_tyty + = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); + expr.iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { - TypeCheckStmt::Resolve (s); + 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); + if (is_final_expr) + { + delete block_tyty; + block_tyty = infered; + } + return true; }); + + if (expr.has_expr ()) + { + auto tail_tyty = TypeCheckExpr::Resolve (expr.expr.get (), true); + + delete block_tyty; + block_tyty = tail_tyty; + } + + // 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; } // RUST_HIR_TYPE_CHECK_STRUCT_FIELD diff --git a/gcc/rust/typecheck/rust-tyty-resolver.h b/gcc/rust/typecheck/rust-tyty-resolver.h index 2851a1e..e2678c2 100644 --- a/gcc/rust/typecheck/rust-tyty-resolver.h +++ b/gcc/rust/typecheck/rust-tyty-resolver.h @@ -73,8 +73,6 @@ public: d.parent, &hir_node_ref); rust_assert (ok); - printf ("failed lets try [%u]\n", hir_node_ref); - if (!context->lookup_type (hir_node_ref, &resolved)) { rust_fatal_error ( @@ -102,10 +100,8 @@ public: &resolved_type); rust_assert (ok); - if (!resolved_type->is_unit ()) - { - return true; - } + if (resolved_type->get_kind () != TyTy::TypeKind::INFER) + return true; auto resolved_tyty = resolved_type; for (auto it : gathered_types) diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 615ef80..46ba633 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -34,58 +34,83 @@ public: virtual void visit (UnitType &type) override { - Location locus = mappings->lookup_location (type.get_ref ()); - rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), - type.as_string ().c_str ()); + 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_fatal_error (def_locus, "declared here"); + } + + 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_fatal_error (def_locus, "declared here"); } virtual void visit (InferType &type) override { - Location locus = mappings->lookup_location (type.get_ref ()); - rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), - type.as_string ().c_str ()); + 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_fatal_error (def_locus, "declared here"); } virtual void visit (FnType &type) override { - Location locus = mappings->lookup_location (type.get_ref ()); - rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), - type.as_string ().c_str ()); + 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_fatal_error (def_locus, "declared here"); } virtual void visit (ParamType &type) override { - Location locus = mappings->lookup_location (type.get_ref ()); - rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), - type.as_string ().c_str ()); + 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_fatal_error (def_locus, "declared here"); } virtual void visit (ArrayType &type) override { - Location locus = mappings->lookup_location (type.get_ref ()); - rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), - type.as_string ().c_str ()); + 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_fatal_error (def_locus, "declared here"); } virtual void visit (BoolType &type) override { - Location locus = mappings->lookup_location (type.get_ref ()); - rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), - type.as_string ().c_str ()); + 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_fatal_error (def_locus, "declared here"); } virtual void visit (IntType &type) override { - Location locus = mappings->lookup_location (type.get_ref ()); - rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), - type.as_string ().c_str ()); + 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_fatal_error (def_locus, "declared here"); } virtual void visit (UintType &type) override { - Location locus = mappings->lookup_location (type.get_ref ()); - rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), - type.as_string ().c_str ()); + 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_fatal_error (def_locus, "declared here"); } protected: @@ -114,6 +139,11 @@ public: // we are an inference variable so this means we can take the other as the // type + virtual void visit (UnitType &type) override + { + resolved = new UnitType (type.get_ref ()); + } + virtual void visit (BoolType &type) override { resolved = new BoolType (type.get_ref ()); @@ -165,6 +195,8 @@ public: return resolved; } + void visit (IntType &type) override { rust_assert (false); } + private: UnitType *base; TyBase *resolved; diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 59c4bcb..c7c609e 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -49,7 +49,7 @@ class TyVisitor; class TyBase { public: - ~TyBase () {} + virtual ~TyBase () {} HirId get_ref () const { return ref; } diff --git a/gcc/testsuite/rust.test/compilable/deadcode1.rs b/gcc/testsuite/rust.test/compilable/deadcode1.rs new file mode 100644 index 0000000..ec6e240 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/deadcode1.rs @@ -0,0 +1,18 @@ +fn test1() -> i32 { + return 2; + 1 +} + +fn test2(x: i32) -> i32 { + if x > 1 { + return 5; + } else { + return 0; + } + return 1; +} + +fn main() { + let call1 = test1(); + let call2 = test2(2); +} diff --git a/gcc/testsuite/rust.test/compilable/implicit_returns1.rs b/gcc/testsuite/rust.test/compilable/implicit_returns1.rs new file mode 100644 index 0000000..49457c6 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/implicit_returns1.rs @@ -0,0 +1,65 @@ +fn test1() -> i32 { + 1 +} + +fn test2() -> i32 { + return 2; +} + +fn test3(x: i32) -> i32 { + if x > 1 { + 5 + } else { + 0 + } +} + +fn test4(x: i32) -> i32 { + if x > 1 { + return 1; + } + 0 +} + +fn test5(x: i32) -> i32 { + if x > 1 { + if x == 5 { + 7 + } else { + 9 + } + } else { + 0 + } +} + +fn test6(x: i32) -> i32 { + if x > 1 { + return 5; + } else { + return 0; + } +} + +fn test7(x: i32) -> i32 { + if x > 1 { + return 5; + } else { + return 0; + } +} + +fn test8() -> i32 { + return 1; +} + +fn main() { + let call1 = test1(); + let call2 = test2(); + let call3 = test3(3); + let call4 = test4(4); + let call5 = test5(5); + let call6 = test6(6); + let call7 = test7(7); + let call8 = test8(); +} diff --git a/gcc/testsuite/rust.test/fail_compilation/missing_return1.rs b/gcc/testsuite/rust.test/fail_compilation/missing_return1.rs new file mode 100644 index 0000000..500d007 --- /dev/null +++ b/gcc/testsuite/rust.test/fail_compilation/missing_return1.rs @@ -0,0 +1,5 @@ +fn test1() -> i32 {} + +fn main() { + let call1 = test1(); +} -- cgit v1.1 From 06d946d52234e2776be002662439d43e3d557673 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 6 Jan 2021 12:54:57 +0000 Subject: Respect the f32 and f64 suffix on literals Rust is permissive for integers being marked as floats so the check in the lexer can be removed here. --- gcc/rust/backend/rust-compile-expr.h | 4 ---- gcc/rust/hir/tree/rust-hir.h | 2 ++ gcc/rust/lex/rust-lex.cc | 10 --------- gcc/rust/typecheck/rust-hir-type-check-expr.h | 25 +++++++++++++++++++++-- gcc/testsuite/rust.test/compilable/float_types.rs | 11 ++++++++++ 5 files changed, 36 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/rust.test/compilable/float_types.rs (limited to 'gcc') diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 9081000..0370129 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -156,8 +156,6 @@ public: return; case HIR::Literal::FLOAT: { - printf ("FLOATY BOYO: [%s]\n", expr.as_string ().c_str ()); - mpfr_t fval; if (mpfr_init_set_str (fval, expr.as_string ().c_str (), 10, MPFR_RNDN) @@ -177,8 +175,6 @@ public: return; } - printf ("tyty float is [%s]\n", tyty->as_string ().c_str ()); - Btype *type = TyTyResolveCompile::compile (ctx, tyty); translated = ctx->get_backend ()->float_constant_expression (type, fval); diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h index 7417a32..5d758ee 100644 --- a/gcc/rust/hir/tree/rust-hir.h +++ b/gcc/rust/hir/tree/rust-hir.h @@ -257,6 +257,8 @@ public: return Literal ("", CHAR, PrimitiveCoreType::CORETYPE_UNKNOWN); } + void set_lit_type (LitType lt) { type = lt; } + // Returns whether literal is in an invalid state. bool is_error () const { return value_as_string == ""; } }; diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc index b97eea1..4606a6c 100644 --- a/gcc/rust/lex/rust-lex.cc +++ b/gcc/rust/lex/rust-lex.cc @@ -1938,16 +1938,6 @@ Lexer::parse_decimal_int_or_float (Location loc) PrimitiveCoreType type_hint = type_suffix_pair.first; length += type_suffix_pair.second; - if (type_hint == CORETYPE_F32 || type_hint == CORETYPE_F64) - { - rust_error_at ( - get_current_location (), - "invalid type suffix %qs for integer (decimal) literal", - get_type_hint_string (type_hint)); - // ignore invalid type suffix as everything else seems fine - type_hint = CORETYPE_UNKNOWN; - } - current_column += length; str.shrink_to_fit (); diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 29244a6..f2014a1 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -188,6 +188,15 @@ public: ok = context->lookup_builtin ("u128", &infered); break; + case CORETYPE_F32: + expr.get_literal ()->set_lit_type (HIR::Literal::LitType::FLOAT); + ok = context->lookup_builtin ("f32", &infered); + break; + case CORETYPE_F64: + expr.get_literal ()->set_lit_type (HIR::Literal::LitType::FLOAT); + ok = context->lookup_builtin ("f64", &infered); + break; + default: ok = context->lookup_builtin ("i32", &infered); break; @@ -197,8 +206,20 @@ public: break; case HIR::Literal::LitType::FLOAT: { - // FIXME need to respect the suffix if applicable - auto ok = context->lookup_builtin ("f32", &infered); + bool ok = false; + + switch (expr.get_literal ()->get_type_hint ()) + { + case CORETYPE_F32: + ok = context->lookup_builtin ("f32", &infered); + break; + case CORETYPE_F64: + ok = context->lookup_builtin ("f64", &infered); + break; + default: + ok = context->lookup_builtin ("f32", &infered); + break; + } rust_assert (ok); } break; diff --git a/gcc/testsuite/rust.test/compilable/float_types.rs b/gcc/testsuite/rust.test/compilable/float_types.rs new file mode 100644 index 0000000..50b392e --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/float_types.rs @@ -0,0 +1,11 @@ +fn main() { + let a1: f32 = 1.0f32; + let a2: f64 = 2.0f64; + let a3: f32 = 3f32; + let a4: f64 = 4f64; + + let b1 = 1.0f32; + let b2 = 2.0f64; + let b3 = 3f32; + let b4 = 4f64; +} -- cgit v1.1 From 5a11dd79fcbcfc8b3fcd41f809c7fa373d637e41 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 8 Jan 2021 15:12:19 +0000 Subject: Make TyTyVisitor a pure abstract class This will help enforce consistency of visitors to fix issues with TyTy unification rules. --- gcc/rust/backend/rust-compile-context.h | 6 ++ gcc/rust/backend/rust-compile-tyty.h | 56 +++++++++++++--- gcc/rust/typecheck/rust-hir-type-check-item.h | 12 ++++ gcc/rust/typecheck/rust-tyctx.cc | 5 +- gcc/rust/typecheck/rust-tyty-call.h | 12 ++++ gcc/rust/typecheck/rust-tyty-resolver.h | 12 ++++ gcc/rust/typecheck/rust-tyty-rules.h | 95 +++++++++++++-------------- gcc/rust/typecheck/rust-tyty-visitor.h | 23 +++---- gcc/rust/typecheck/rust-tyty.cc | 19 ++++++ gcc/rust/typecheck/rust-tyty.h | 15 +++++ 10 files changed, 185 insertions(+), 70 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index d241921..298ff50 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -221,12 +221,18 @@ public: virtual ~TyTyResolveCompile () {} + 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 (); } + void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } + + void visit (TyTy::ParamType &type) override { gcc_unreachable (); } + void visit (TyTy::ADTType &type) override { ::Btype *compiled_type = nullptr; diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index 2d4e1f0..137b74b 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -43,13 +43,19 @@ public: ~TyTyCompile () {} - void visit (TyTy::InferType &type) override - { - // there shouldn't be any of these left - gcc_unreachable (); - } + 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 (); } - void visit (TyTy::UnitType &type) override {} + void visit (TyTy::ParamType &type) override { gcc_unreachable (); } + + void visit (TyTy::ADTType &type) override { gcc_unreachable (); } + + void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } void visit (TyTy::FnType &type) override { @@ -82,8 +88,6 @@ public: mappings->lookup_location (type.get_ref ())); } - void visit (TyTy::ParamType &type) override {} - void visit (TyTy::BoolType &type) override { translated = backend->named_type ("bool", backend->bool_type (), @@ -205,6 +209,18 @@ public: ~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; @@ -234,6 +250,18 @@ public: ~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; @@ -261,6 +289,18 @@ public: ~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 ()); diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index adf842c..62320a6 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -43,6 +43,18 @@ public: 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::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 { state = type.return_type (); } private: diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc index 6eb46ff..cd171d1 100644 --- a/gcc/rust/typecheck/rust-tyctx.cc +++ b/gcc/rust/typecheck/rust-tyctx.cc @@ -69,7 +69,10 @@ TypeCheckContext::lookup_type (HirId id, TyTy::TyBase **type) { auto it = resolved.find (id); if (it == resolved.end ()) - return false; + { + *type = new TyTy::ErrorType (id); + return false; + } *type = it->second; return true; diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h index d1341df..c3fcb1a 100644 --- a/gcc/rust/typecheck/rust-tyty-call.h +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -38,6 +38,18 @@ public: } ~TypeCheckCallExpr () {} + 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 (); } + void visit (IntType &type) override { gcc_unreachable (); } + void visit (UintType &type) override { gcc_unreachable (); } + void visit (FloatType &type) override { gcc_unreachable (); } + void visit (ErrorType &type) override { gcc_unreachable (); } + void visit (FnType &type) override; private: diff --git a/gcc/rust/typecheck/rust-tyty-resolver.h b/gcc/rust/typecheck/rust-tyty-resolver.h index e2678c2..3d2196a 100644 --- a/gcc/rust/typecheck/rust-tyty-resolver.h +++ b/gcc/rust/typecheck/rust-tyty-resolver.h @@ -151,6 +151,18 @@ public: 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::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 (); } + 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: diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 46ba633..677013f 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -113,23 +113,48 @@ public: rust_fatal_error (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_fatal_error (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_fatal_error (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_fatal_error (def_locus, "declared here"); + } + protected: - BaseRules (TyBase *base) : mappings (Analysis::Mappings::get ()), base (base) + BaseRules (TyBase *base) + : mappings (Analysis::Mappings::get ()), base (base), + resolved (new ErrorType (base->get_ref ())) {} Analysis::Mappings *mappings; - -private: TyBase *base; + TyBase *resolved; }; class InferRules : protected BaseRules { public: - InferRules (InferType *base) - : BaseRules (base), base (base), resolved (nullptr) - {} - ~InferRules () {} + InferRules (InferType *base) : BaseRules (base), base (base) {} TyBase *combine (TyBase *other) { @@ -139,36 +164,34 @@ public: // we are an inference variable so this means we can take the other as the // type - virtual void visit (UnitType &type) override + void visit (UnitType &type) override { resolved = new UnitType (type.get_ref ()); } - virtual void visit (BoolType &type) override + void visit (BoolType &type) override { resolved = new BoolType (type.get_ref ()); } - virtual void visit (IntType &type) override + void visit (IntType &type) override { resolved = new IntType (type.get_ref (), type.get_kind ()); } - virtual void visit (UintType &type) override + void visit (UintType &type) override { resolved = new UintType (type.get_ref (), type.get_kind ()); } private: InferType *base; - TyBase *resolved; }; class StructFieldTypeRules : protected BaseRules { public: - StructFieldTypeRules (StructFieldType *base) - : BaseRules (base), base (base), resolved (nullptr) + StructFieldTypeRules (StructFieldType *base) : BaseRules (base), base (base) {} TyBase *combine (TyBase *other) @@ -179,15 +202,12 @@ public: private: StructFieldType *base; - TyBase *resolved; }; class UnitRules : protected BaseRules { public: - UnitRules (UnitType *base) : BaseRules (base), base (base), resolved (nullptr) - {} - ~UnitRules () {} + UnitRules (UnitType *base) : BaseRules (base), base (base) {} TyBase *combine (TyBase *other) { @@ -199,14 +219,12 @@ public: private: UnitType *base; - TyBase *resolved; }; class FnRules : protected BaseRules { public: - FnRules (FnType *base) : BaseRules (base), base (base), resolved (nullptr) {} - ~FnRules () {} + FnRules (FnType *base) : BaseRules (base), base (base) {} TyBase *combine (TyBase *other) { @@ -216,16 +234,12 @@ public: private: FnType *base; - TyBase *resolved; }; class ParamRules : protected BaseRules { public: - ParamRules (ParamType *base) - : BaseRules (base), base (base), resolved (nullptr) - {} - ~ParamRules () {} + ParamRules (ParamType *base) : BaseRules (base), base (base) {} TyBase *combine (TyBase *other) { @@ -235,17 +249,12 @@ public: private: ParamType *base; - TyBase *resolved; }; class ArrayRules : protected BaseRules { public: - ArrayRules (ArrayType *base) - : BaseRules (base), base (base), resolved (nullptr) - {} - - ~ArrayRules () {} + ArrayRules (ArrayType *base) : BaseRules (base), base (base) {} TyBase *combine (TyBase *other) { @@ -274,15 +283,12 @@ public: private: ArrayType *base; - TyBase *resolved; }; class BoolRules : protected BaseRules { public: - BoolRules (BoolType *base) : BaseRules (base), base (base), resolved (nullptr) - {} - ~BoolRules () {} + BoolRules (BoolType *base) : BaseRules (base), base (base) {} TyBase *combine (TyBase *other) { @@ -297,15 +303,12 @@ public: private: BoolType *base; - TyBase *resolved; }; class IntRules : protected BaseRules { public: - IntRules (IntType *base) : BaseRules (base), base (base), resolved (nullptr) - {} - ~IntRules () {} + IntRules (IntType *base) : BaseRules (base), base (base) {} TyBase *combine (TyBase *other) { @@ -321,15 +324,12 @@ public: private: IntType *base; - TyBase *resolved; }; class UintRules : protected BaseRules { public: - UintRules (UintType *base) : BaseRules (base), base (base), resolved (nullptr) - {} - ~UintRules () {} + UintRules (UintType *base) : BaseRules (base), base (base) {} TyBase *combine (TyBase *other) { @@ -345,16 +345,12 @@ public: private: UintType *base; - TyBase *resolved; }; class FloatRules : protected BaseRules { public: - FloatRules (FloatType *base) - : BaseRules (base), base (base), resolved (nullptr) - {} - ~FloatRules () {} + FloatRules (FloatType *base) : BaseRules (base), base (base) {} TyBase *combine (TyBase *other) { @@ -370,7 +366,6 @@ public: private: FloatType *base; - TyBase *resolved; }; } // namespace TyTy diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h index 40998ca..def43cd 100644 --- a/gcc/rust/typecheck/rust-tyty-visitor.h +++ b/gcc/rust/typecheck/rust-tyty-visitor.h @@ -27,17 +27,18 @@ namespace TyTy { class TyVisitor { public: - virtual void visit (UnitType &type) {} - virtual void visit (InferType &type) {} - virtual void visit (StructFieldType &type) {} - virtual void visit (ADTType &type) {} - virtual void visit (FnType &type) {} - virtual void visit (ParamType &type) {} - virtual void visit (ArrayType &type) {} - virtual void visit (BoolType &type) {} - virtual void visit (IntType &type) {} - virtual void visit (UintType &type) {} - virtual void visit (FloatType &type) {} + virtual void visit (UnitType &type) = 0; + virtual void visit (InferType &type) = 0; + 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; + virtual void visit (UintType &type) = 0; + virtual void visit (FloatType &type) = 0; + virtual void visit (ErrorType &type) = 0; }; } // namespace TyTy diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 0cefab6..033f839 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -64,6 +64,25 @@ InferType::combine (TyBase *other) } void +ErrorType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +ErrorType::as_string () const +{ + return ""; +} + +TyBase * +ErrorType::combine (TyBase *other) +{ + // rust_error_at (); + return this; +} + +void StructFieldType::accept_vis (TyVisitor &vis) { vis.visit (*this); diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index c7c609e..be7ec0c 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -43,6 +43,7 @@ enum TypeKind UNIT, FIELD, // there are more to add... + ERROR }; class TyVisitor; @@ -84,6 +85,20 @@ public: TyBase *combine (TyBase *other) override; }; +class ErrorType : public TyBase +{ +public: + ErrorType (HirId ref) : TyBase (ref, TypeKind::ERROR) {} + + void accept_vis (TyVisitor &vis) override; + + bool is_unit () const override { return true; } + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; +}; + class UnitType : public TyBase { public: -- cgit v1.1 From 705b8b73aa694a8cc79c4459beca192145f97542 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 8 Jan 2021 15:34:13 +0000 Subject: There was a bug with LetStmts where we name resolved the identifier pattern first before the init expression. This lead to a situation where shadowing rules were broken. Example: let x = 1; let x = x + 1; In this example the code was referencing the 2nd LetStmt as the resolved name for the Identifier reference. --- gcc/rust/resolve/rust-ast-resolve-stmt.h | 6 +++--- gcc/testsuite/rust.test/compilable/shadow2.rs | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/rust.test/compilable/shadow2.rs (limited to 'gcc') diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h index 87b3cf3..6d751e6 100644 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h @@ -51,12 +51,12 @@ public: void visit (AST::LetStmt &stmt) { + if (stmt.has_init_expr ()) + ResolveExpr::go (stmt.get_init_expr ().get (), stmt.get_node_id ()); + PatternDeclaration::go (stmt.get_pattern ().get (), stmt.get_node_id ()); if (stmt.has_type ()) ResolveType::go (stmt.get_type ().get (), stmt.get_node_id ()); - - if (stmt.has_init_expr ()) - ResolveExpr::go (stmt.get_init_expr ().get (), stmt.get_node_id ()); } private: diff --git a/gcc/testsuite/rust.test/compilable/shadow2.rs b/gcc/testsuite/rust.test/compilable/shadow2.rs new file mode 100644 index 0000000..fbac8c0 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/shadow2.rs @@ -0,0 +1,4 @@ +fn main() { + let x = 1; + let x = x + 1; +} -- cgit v1.1 From 6d7a53b684b5765acda82f39f71bc7798bf0ee94 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 8 Jan 2021 16:21:59 +0000 Subject: Fix crash when compiling BlockExpr's This ensures the compiler respects scoping and shadowing rules of blocks added within an enclosing scope. --- gcc/rust/hir/rust-ast-lower-block.h | 5 +++++ gcc/testsuite/rust.test/compilable/scoping1.rs | 10 ++++++++++ 2 files changed, 15 insertions(+) create mode 100644 gcc/testsuite/rust.test/compilable/scoping1.rs (limited to 'gcc') diff --git a/gcc/rust/hir/rust-ast-lower-block.h b/gcc/rust/hir/rust-ast-lower-block.h index 1ef581e..f81a242 100644 --- a/gcc/rust/hir/rust-ast-lower-block.h +++ b/gcc/rust/hir/rust-ast-lower-block.h @@ -129,6 +129,11 @@ public: translated = ASTLoweringIfBlock::translate (&expr, &terminated); } + void visit (AST::BlockExpr &expr) + { + translated = ASTLoweringBlock::translate (&expr, &terminated); + } + private: ASTLoweringExprWithBlock () : ASTLoweringBase (), translated (nullptr), terminated (false) diff --git a/gcc/testsuite/rust.test/compilable/scoping1.rs b/gcc/testsuite/rust.test/compilable/scoping1.rs new file mode 100644 index 0000000..02b5f93 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/scoping1.rs @@ -0,0 +1,10 @@ +fn main() { + let x = 1; + { + let x = true; + { + x = false; + } + } + let x = x + 1; +} -- cgit v1.1 From 0f42a240e53e932de0ae4799d54fe0bd15d06047 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 8 Jan 2021 16:49:06 +0000 Subject: Functions with parameters much receive their own scoping Rib This means that paramters are scoped and shadowed correctly. Currently the resolver is treating all paramters are shadowing each other if they have the same name which is incorrect. --- gcc/rust/resolve/rust-ast-resolve-item.h | 27 +++++++++++---------------- gcc/rust/resolve/rust-ast-resolve.cc | 3 +++ 2 files changed, 14 insertions(+), 16 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index c69e433..310d296 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -65,6 +65,14 @@ public: ResolveType::go (function.get_return_type ().get (), function.get_node_id ()); + NodeId scope_node_id = function.get_node_id (); + resolver->get_name_scope ().push (scope_node_id); + resolver->get_type_scope ().push (scope_node_id); + resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); + resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); + + // we make a new scope so the names of parameters are resolved and shadowed + // correctly for (auto ¶m : function.get_function_params ()) { ResolveType::go (param.get_type ().get (), param.get_node_id ()); @@ -72,22 +80,9 @@ public: param.get_node_id ()); } - // setup parent scoping for names - NodeId scope_node_id = function.get_definition ()->get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - - function.get_definition ()->iterate_stmts ( - [&] (AST::Stmt *s) mutable -> bool { - ResolveStmt::go (s, s->get_node_id ()); - return true; - }); - - if (function.get_definition ()->has_tail_expr ()) - ResolveExpr::go (function.get_definition ()->get_tail_expr ().get (), - function.get_node_id ()); + // resolve the function body + ResolveExpr::go (function.get_definition ().get (), + function.get_node_id ()); resolver->get_name_scope ().pop (); resolver->get_type_scope ().pop (); diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index fe8d7e0..e5b0942 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -285,6 +285,9 @@ ResolveExpr::visit (AST::BlockExpr &expr) return true; }); + if (expr.has_tail_expr ()) + ResolveExpr::go (expr.get_tail_expr ().get (), expr.get_node_id ()); + resolver->get_name_scope ().pop (); resolver->get_type_scope ().pop (); } -- cgit v1.1