aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-01-12 17:12:00 +0000
committerPhilip Herron <herron.philip@googlemail.com>2021-01-16 14:15:09 +0000
commite4a2a52b35e99a40f8bd3992a6b53650908fd188 (patch)
tree15df17d22c70ada60c27af51cd89a5dd1dba5e01 /gcc
parentd96e1594dd378078987900819afc611bd0db19b0 (diff)
downloadgcc-e4a2a52b35e99a40f8bd3992a6b53650908fd188.zip
gcc-e4a2a52b35e99a40f8bd3992a6b53650908fd188.tar.gz
gcc-e4a2a52b35e99a40f8bd3992a6b53650908fd188.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/backend/rust-compile-context.h10
-rw-r--r--gcc/rust/backend/rust-compile-item.h2
-rw-r--r--gcc/rust/backend/rust-compile.cc2
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.h7
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.h3
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc21
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h9
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h94
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.h6
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-toplevel.h7
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h1
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc12
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h94
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc87
-rw-r--r--gcc/rust/typecheck/rust-tyty.h107
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/implicit_returns_err1.rs12
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/implicit_returns_err2.rs8
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/implicit_returns_err3.rs9
18 files changed, 375 insertions, 116 deletions
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<HIR::BlockExpr> (
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<HIR::ExprWithoutBlock> (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<Attribute> inner_attrs;
- // bool has_statements;
std::vector<std::unique_ptr<Stmt> > statements;
- // bool has_expr;
std::unique_ptr<ExprWithoutBlock> 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<std::unique_ptr<Stmt> > block_statements,
- std::unique_ptr<ExprWithoutBlock> block_expr,
+ std::unique_ptr<ExprWithoutBlock> block_expr, bool tail_reachable,
std::vector<Attribute> inner_attribs,
std::vector<Attribute> 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<TyTy::ParamType *> params;
for (auto &param : 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<StructFieldType *> 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<ParamType *> 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<StructFieldType *> 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<StructFieldType *> 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<StructFieldType *> 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<ParamType *> 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<ParamType *> 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<ParamType *> 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;
};
diff --git a/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err1.rs b/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err1.rs
new file mode 100644
index 0000000..b450e18
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err1.rs
@@ -0,0 +1,12 @@
+fn test(x: i32) -> i32 {
+ if x > 1 {
+ 1
+ } else {
+ 2
+ }
+ 3
+}
+
+fn main() {
+ let a = test(1);
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err2.rs b/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err2.rs
new file mode 100644
index 0000000..b5fbd0a
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err2.rs
@@ -0,0 +1,8 @@
+fn test(x: i32) -> i32 {
+ return 1;
+ true
+}
+
+fn main() {
+ let a = test(1);
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err3.rs b/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err3.rs
new file mode 100644
index 0000000..a83385e
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err3.rs
@@ -0,0 +1,9 @@
+fn test(x: i32) -> i32 {
+ if x > 1 {
+ 1
+ }
+}
+
+fn main() {
+ let a = test(9);
+}