aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-01-21 17:31:21 +0000
committerPhilip Herron <herron.philip@googlemail.com>2021-01-26 11:59:39 +0000
commit0817c29a423aca1c4c3f9ba812f67df35f36fc65 (patch)
tree942c0d79f3f5063361fb0cae8057bb8ab8b29940
parent5294dfe7dce7a58fbaf2131c7589d115008ebf0e (diff)
downloadgcc-0817c29a423aca1c4c3f9ba812f67df35f36fc65.zip
gcc-0817c29a423aca1c4c3f9ba812f67df35f36fc65.tar.gz
gcc-0817c29a423aca1c4c3f9ba812f67df35f36fc65.tar.bz2
Add Integer and Float InterenceVariable
In order to properly handle all integer types and infer we must follow HM algorithm. This means when we unify every type in the resolver this should keep a chain of HirId of references such that when/if the type is resolved it lookup tables can be updated for the Backend to compile to Gimple. Consider the case: fn test(x:u32) -> u32 {...} let a = test(1); The VarDecl here will have the type let a:<I?> = test<u32>(1<I?>). Since this integer combines with the parameter x:u32 the type resolver knows at this point these must be a u32. let a; a = 1; let b:u32 = a; This is more subtle let a:<?> a:<?> = 1<I?> let b:u32 = a<I?>; Since the integer inference variable combines with u32 all previous references can be updated to u32 at this point. In the basic case of: let a; a = 1; This resolves down to: let a:<I?>; a<I?> = 1<I?> It is not until we complete type-inference we can iterate all the resolved types and HirIds and default any <I?> to i32 and any <F?> to f32. Any remaining general inference variable are errors.
-rw-r--r--gcc/rust/backend/rust-compile-context.h31
-rw-r--r--gcc/rust/backend/rust-compile-expr.h8
-rw-r--r--gcc/rust/backend/rust-compile-tyty.h2
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h6
-rw-r--r--gcc/rust/hir/tree/rust-hir-full-test.cc18
-rw-r--r--gcc/rust/hir/tree/rust-hir.h7
-rw-r--r--gcc/rust/rust-session-manager.cc5
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h249
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.h62
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-stmt.h22
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-toplevel.h16
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h32
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc134
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h9
-rw-r--r--gcc/rust/typecheck/rust-tycheck-dump.h178
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.h14
-rw-r--r--gcc/rust/typecheck/rust-tyty-resolver.h214
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h372
-rw-r--r--gcc/rust/typecheck/rust-tyty-visitor.h1
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc126
-rw-r--r--gcc/rust/typecheck/rust-tyty.h183
-rw-r--r--gcc/rust/util/rust-hir-map.cc1
-rw-r--r--gcc/rust/util/rust-hir-map.h8
-rw-r--r--gcc/testsuite/rust.test/compilable/ints_infer1.rs18
-rw-r--r--gcc/testsuite/rust.test/compilable/type_infer6.rs12
25 files changed, 1115 insertions, 613 deletions
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index df29e36..ed03f02 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -298,6 +298,37 @@ public:
translated = named_struct;
}
+ void visit (TyTy::TupleType &type) override
+ {
+ bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &translated);
+ if (ok)
+ return;
+
+ // create implicit struct
+ std::vector<Backend::Btyped_identifier> fields;
+ for (size_t i = 0; i < type.num_fields (); i++)
+ {
+ TyTy::TyBase *field = type.get_field (i);
+ Btype *compiled_field_ty
+ = TyTyCompile::compile (ctx->get_backend (), field);
+
+ Backend::Btyped_identifier f (std::to_string (i), compiled_field_ty,
+ ctx->get_mappings ()->lookup_location (
+ type.get_ty_ref ()));
+ fields.push_back (std::move (f));
+ }
+
+ Btype *struct_type_record = ctx->get_backend ()->struct_type (fields);
+ Btype *named_struct
+ = ctx->get_backend ()->named_type (type.as_string (), struct_type_record,
+ ctx->get_mappings ()->lookup_location (
+ type.get_ty_ref ()));
+
+ ctx->push_type (named_struct);
+ ctx->insert_compiled_type (type.get_ty_ref (), named_struct);
+ translated = named_struct;
+ }
+
void visit (TyTy::ArrayType &type) override
{
mpz_t ival;
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index da3c9cd..7c2f32d 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -145,17 +145,19 @@ public:
void visit (HIR::LiteralExpr &expr)
{
+ auto literal_value = expr.get_literal ();
switch (expr.get_lit_type ())
{
case HIR::Literal::BOOL: {
- bool bval = expr.as_string ().compare ("true") == 0;
+ bool bval = literal_value->as_string ().compare ("true") == 0;
translated = ctx->get_backend ()->boolean_constant_expression (bval);
}
return;
case HIR::Literal::INT: {
mpz_t ival;
- if (mpz_init_set_str (ival, expr.as_string ().c_str (), 10) != 0)
+ if (mpz_init_set_str (ival, literal_value->as_string ().c_str (), 10)
+ != 0)
{
rust_fatal_error (expr.get_locus (), "bad number in literal");
return;
@@ -178,7 +180,7 @@ public:
case HIR::Literal::FLOAT: {
mpfr_t fval;
- if (mpfr_init_set_str (fval, expr.as_string ().c_str (), 10,
+ if (mpfr_init_set_str (fval, literal_value->as_string ().c_str (), 10,
MPFR_RNDN)
!= 0)
{
diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h
index f74b4ac..b6794bc 100644
--- a/gcc/rust/backend/rust-compile-tyty.h
+++ b/gcc/rust/backend/rust-compile-tyty.h
@@ -52,6 +52,8 @@ public:
void visit (TyTy::ADTType &type) override { gcc_unreachable (); }
+ void visit (TyTy::TupleType &type) override { gcc_unreachable (); }
+
void visit (TyTy::ArrayType &type) override { gcc_unreachable (); }
void visit (TyTy::UnitType &type) override
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index 0ce678b..69b680d 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -61,7 +61,11 @@ class LiteralExpr : public ExprWithoutBlock
Location locus;
public:
- std::string as_string () const override { return literal.as_string (); }
+ std::string as_string () const override
+ {
+ return "( " + literal.as_string () + " (" + get_mappings ().as_string ()
+ + "))";
+ }
Literal::LitType get_lit_type () const { return literal.get_lit_type (); }
diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc
index f4e9f5a..b727917 100644
--- a/gcc/rust/hir/tree/rust-hir-full-test.cc
+++ b/gcc/rust/hir/tree/rust-hir-full-test.cc
@@ -2072,23 +2072,15 @@ ArithmeticOrLogicalExpr::as_string () const
operator_str = ">>";
break;
default:
- operator_str = "invalid operator. wtf";
+ gcc_unreachable ();
break;
}
- std::string str ("ArithmeticOrLogicalExpr: ");
- if (main_or_left_expr == nullptr || right_expr == nullptr)
- {
- str += "error. this is probably a parsing failure.";
- }
- else
- {
- str += main_or_left_expr->as_string () + " ";
- str += operator_str + " ";
- str += right_expr->as_string ();
- }
+ std::string str = main_or_left_expr->as_string () + " ";
+ str += operator_str + " ";
+ str += right_expr->as_string ();
- return str + "::" + get_mappings ().as_string ();
+ return "( " + str + " (" + get_mappings ().as_string () + "))";
}
std::string
diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h
index fabc31d..e4a81c5 100644
--- a/gcc/rust/hir/tree/rust-hir.h
+++ b/gcc/rust/hir/tree/rust-hir.h
@@ -895,7 +895,10 @@ public:
ident (std::move (ident)), locus (locus)
{}
- std::string as_string () const override { return ident; }
+ std::string as_string () const override
+ {
+ return "( " + ident + " (" + get_mappings ().as_string () + "))";
+ }
Location get_locus () const { return locus; }
Location get_locus_slow () const override { return get_locus (); }
@@ -908,6 +911,8 @@ public:
return std::unique_ptr<IdentifierExpr> (clone_identifier_expr_impl ());
}
+ Identifier get_identifier () const { return ident; }
+
protected:
// Clone method implementation
IdentifierExpr *clone_expr_without_block_impl () const override
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index c1df913..281049d 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -34,6 +34,7 @@
#include "rust-ast-resolve.h"
#include "rust-ast-lower.h"
#include "rust-hir-type-check.h"
+#include "rust-tycheck-dump.h"
#include "rust-compile.h"
extern Linemap *
@@ -548,6 +549,10 @@ Session::parse_file (const char *filename)
// type resolve
type_resolution (hir);
+ // FIXME this needs an option of itself
+ // auto buf = Resolver::TypeResolverDump::go (hir);
+ // fprintf (stderr, "%s\n", buf.c_str ());
+
if (saw_errors ())
return;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 02830cd..8f60f72 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -23,7 +23,6 @@
#include "rust-hir-full.h"
#include "rust-tyty.h"
#include "rust-tyty-call.h"
-#include "rust-tyty-resolver.h"
#include "rust-hir-type-check-struct-field.h"
namespace Rust {
@@ -38,10 +37,15 @@ public:
expr->accept_vis (resolver);
if (resolver.infered == nullptr)
- resolver.infered
- = new TyTy::UnitType (expr->get_mappings ().get_hirid ());
+ {
+ resolver.infered
+ = new TyTy::UnitType (expr->get_mappings ().get_hirid ());
+ }
+ auto ref = expr->get_mappings ().get_hirid ();
+ resolver.infered->set_ref (ref);
resolver.context->insert_type (expr->get_mappings (), resolver.infered);
+
return resolver.infered;
}
@@ -54,14 +58,40 @@ public:
"failed to resolve TupleIndexExpr receiver");
return;
}
- if (resolved->get_kind () != TyTy::TypeKind::ADT)
+
+ bool is_valid_type = resolved->get_kind () == TyTy::TypeKind::ADT
+ || resolved->get_kind () == TyTy::TypeKind::TUPLE;
+ if (!is_valid_type)
{
rust_error_at (expr.get_tuple_expr ()->get_locus_slow (),
- "Expected ADT type got: %s",
+ "Expected Tuple or ADT got: %s",
resolved->as_string ().c_str ());
return;
}
+ if (resolved->get_kind () == TyTy::TypeKind::TUPLE)
+ {
+ TyTy::TupleType *tuple = (TyTy::TupleType *) resolved;
+ TupleIndex index = expr.get_tuple_index ();
+ if ((size_t) index >= tuple->num_fields ())
+ {
+ rust_error_at (expr.get_locus (), "unknown field at index %i",
+ index);
+ return;
+ }
+
+ auto field_tyty = tuple->get_field ((size_t) index);
+ if (field_tyty == nullptr)
+ {
+ rust_error_at (expr.get_locus (),
+ "failed to lookup field type at index %i", index);
+ return;
+ }
+
+ infered = field_tyty;
+ return;
+ }
+
TyTy::ADTType *adt = (TyTy::ADTType *) resolved;
TupleIndex index = expr.get_tuple_index ();
if ((size_t) index >= adt->num_fields ())
@@ -94,34 +124,32 @@ public:
return;
}
- size_t index = 0;
- std::string identifier = "(";
- std::vector<TyTy::StructFieldType *> fields;
+ std::vector<HirId> fields;
for (auto &elem : expr.get_tuple_elems ())
{
auto field_ty = TypeCheckExpr::Resolve (elem.get ());
- identifier += field_ty->as_string ();
- if ((index + 1) < expr.get_tuple_elems ().size ())
- identifier += ",";
-
- auto field_tyty
- = new TyTy::StructFieldType (elem->get_mappings ().get_hirid (),
- std::to_string (index), field_ty);
- fields.push_back (field_tyty);
- index++;
- }
- identifier += ")";
- infered = new TyTy::ADTType (expr.get_mappings ().get_hirid (), identifier,
- true, fields);
+ fields.push_back (field_ty->get_ref ());
+ }
+ infered = new TyTy::TupleType (expr.get_mappings ().get_hirid (), fields);
}
void visit (HIR::ReturnExpr &expr)
{
- auto ret = context->peek_return_type ();
- rust_assert (ret != nullptr);
+ auto fn_return_tyty = context->peek_return_type ();
+ rust_assert (fn_return_tyty != nullptr);
auto expr_ty = TypeCheckExpr::Resolve (expr.get_expr ());
- infered = ret->combine (expr_ty);
+ if (expr_ty == nullptr)
+ {
+ rust_error_at (expr.get_locus (),
+ "failed to resolve type for ReturnExpr");
+ return;
+ }
+
+ infered = fn_return_tyty->combine (expr_ty);
+ fn_return_tyty->append_reference (expr_ty->get_ref ());
+ for (auto &ref : infered->get_combined_refs ())
+ fn_return_tyty->append_reference (ref);
}
void visit (HIR::CallExpr &expr)
@@ -163,15 +191,13 @@ public:
return;
}
- infered = TyTy::TypeCheckCallExpr::go (lookup, expr);
+ infered = TyTy::TypeCheckCallExpr::go (lookup, expr, context);
if (infered == nullptr)
{
rust_error_at (expr.get_locus (), "failed to lookup type to CallExpr");
return;
}
- TyTy::InferType infer (expr.get_mappings ().get_hirid ());
- infered = infer.combine (infered);
infered->set_ref (expr.get_mappings ().get_hirid ());
}
@@ -181,6 +207,12 @@ public:
auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ());
infered = lhs->combine (rhs);
+ if (infered == nullptr)
+ {
+ rust_error_at (expr.get_locus (),
+ "failure in TypeInference AssignmentExpr");
+ return;
+ }
// in the case of declare first for an ADT Type:
//
@@ -191,36 +223,34 @@ public:
// The lhs will have a TyTy of INFER and so when the declaration is
// referenced it will still have an unknown type so we will fail to resolve
// FieldAccessExpr
- if (lhs->get_kind () == TyTy::TypeKind::INFER)
- {
- NodeId ast_node_id = expr.get_lhs ()->get_mappings ().get_nodeid ();
- NodeId ref_node_id;
- if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
- return;
- Definition def;
- if (!resolver->lookup_definition (ref_node_id, &def))
- {
- rust_error_at (expr.get_locus (),
- "assignment infer - unknown reference");
- return;
- }
+ NodeId ast_node_id = expr.get_lhs ()->get_mappings ().get_nodeid ();
+ NodeId ref_node_id;
+ if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
+ return;
- HirId ref;
- if (!mappings->lookup_node_to_hir (
- expr.get_mappings ().get_crate_num (), def.parent, &ref))
- {
- rust_error_at (expr.get_locus (),
- "assignment infer - reverse lookup failure");
- return;
- }
+ Definition def;
+ if (!resolver->lookup_definition (ref_node_id, &def))
+ {
+ rust_error_at (expr.get_locus (),
+ "assignment infer - unknown reference");
+ return;
+ }
- context->insert_type (
- Analysis::NodeMapping (
- expr.get_lhs ()->get_mappings ().get_crate_num (), ref_node_id, ref,
- UNKNOWN_LOCAL_DEFID),
- infered);
+ HirId ref;
+ if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (),
+ def.parent, &ref))
+ {
+ rust_error_at (expr.get_locus (),
+ "assignment infer - reverse lookup failure");
+ return;
}
+
+ // FIXME free the old one
+ context->insert_type (
+ Analysis::NodeMapping (expr.get_lhs ()->get_mappings ().get_crate_num (),
+ ref_node_id, ref, UNKNOWN_LOCAL_DEFID),
+ infered->clone ());
}
void visit (HIR::IdentifierExpr &expr)
@@ -265,8 +295,8 @@ public:
return;
}
- TyTy::InferType infer (expr.get_mappings ().get_hirid ());
- infered = infer.combine (lookup);
+ lookup->append_reference (lookup->get_ref ());
+ infered = lookup->clone ();
infered->set_ref (expr.get_mappings ().get_hirid ());
}
@@ -321,7 +351,10 @@ public:
break;
default:
- ok = context->lookup_builtin ("i32", &infered);
+ ok = true;
+ infered = new TyTy::InferType (
+ expr.get_mappings ().get_hirid (),
+ TyTy::InferType::InferTypeKind::INTEGRAL);
break;
}
rust_assert (ok);
@@ -339,8 +372,12 @@ public:
case CORETYPE_F64:
ok = context->lookup_builtin ("f64", &infered);
break;
+
default:
- ok = context->lookup_builtin ("f32", &infered);
+ ok = true;
+ infered
+ = new TyTy::InferType (expr.get_mappings ().get_hirid (),
+ TyTy::InferType::InferTypeKind::FLOAT);
break;
}
rust_assert (ok);
@@ -358,9 +395,7 @@ public:
break;
}
- TyTy::InferType infer (expr.get_mappings ().get_hirid ());
- infered = infer.combine (infered);
- infered->set_ref (expr.get_mappings ().get_hirid ());
+ infered = infered->clone ();
}
void visit (HIR::ArithmeticOrLogicalExpr &expr)
@@ -380,7 +415,13 @@ public:
case HIR::ArithmeticOrLogicalExpr::MODULUS: {
bool valid = (combined->get_kind () == TyTy::TypeKind::INT)
|| (combined->get_kind () == TyTy::TypeKind::UINT)
- || (combined->get_kind () == TyTy::TypeKind::FLOAT);
+ || (combined->get_kind () == TyTy::TypeKind::FLOAT)
+ || (combined->get_kind () == TyTy::TypeKind::INFER
+ && (((TyTy::InferType *) combined)->get_infer_kind ()
+ == TyTy::InferType::INTEGRAL))
+ || (combined->get_kind () == TyTy::TypeKind::INFER
+ && (((TyTy::InferType *) combined)->get_infer_kind ()
+ == TyTy::InferType::FLOAT));
if (!valid)
{
rust_error_at (expr.get_locus (), "cannot apply operator to %s",
@@ -396,7 +437,10 @@ public:
case HIR::ArithmeticOrLogicalExpr::BITWISE_XOR: {
bool valid = (combined->get_kind () == TyTy::TypeKind::INT)
|| (combined->get_kind () == TyTy::TypeKind::UINT)
- || (combined->get_kind () == TyTy::TypeKind::BOOL);
+ || (combined->get_kind () == TyTy::TypeKind::BOOL)
+ || (combined->get_kind () == TyTy::TypeKind::INFER
+ && (((TyTy::InferType *) combined)->get_infer_kind ()
+ == TyTy::InferType::INTEGRAL));
if (!valid)
{
rust_error_at (expr.get_locus (), "cannot apply operator to %s",
@@ -410,7 +454,10 @@ public:
case HIR::ArithmeticOrLogicalExpr::LEFT_SHIFT:
case HIR::ArithmeticOrLogicalExpr::RIGHT_SHIFT: {
bool valid = (combined->get_kind () == TyTy::TypeKind::INT)
- || (combined->get_kind () == TyTy::TypeKind::UINT);
+ || (combined->get_kind () == TyTy::TypeKind::UINT)
+ || (combined->get_kind () == TyTy::TypeKind::INFER
+ && (((TyTy::InferType *) combined)->get_infer_kind ()
+ == TyTy::InferType::INTEGRAL));
if (!valid)
{
rust_error_at (expr.get_locus (), "cannot apply operator to %s",
@@ -422,6 +469,8 @@ public:
}
infered = combined;
+ infered->append_reference (lhs->get_ref ());
+ infered->append_reference (rhs->get_ref ());
}
void visit (HIR::ComparisonExpr &expr)
@@ -435,6 +484,8 @@ public:
// we expect this to be
infered = new TyTy::BoolType (expr.get_mappings ().get_hirid ());
+ infered->append_reference (lhs->get_ref ());
+ infered->append_reference (rhs->get_ref ());
}
void visit (HIR::LazyBooleanExpr &expr)
@@ -454,6 +505,8 @@ public:
return;
infered = lhs->combine (rhs);
+ infered->append_reference (lhs->get_ref ());
+ infered->append_reference (rhs->get_ref ());
}
void visit (HIR::NegationExpr &expr)
@@ -467,7 +520,13 @@ public:
bool valid
= (negated_expr_ty->get_kind () == TyTy::TypeKind::INT)
|| (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT)
- || (negated_expr_ty->get_kind () == TyTy::TypeKind::FLOAT);
+ || (negated_expr_ty->get_kind () == TyTy::TypeKind::FLOAT)
+ || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER
+ && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind ()
+ == TyTy::InferType::INTEGRAL))
+ || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER
+ && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind ()
+ == TyTy::InferType::FLOAT));
if (!valid)
{
rust_error_at (expr.get_locus (), "cannot apply unary - to %s",
@@ -481,7 +540,10 @@ public:
bool valid
= (negated_expr_ty->get_kind () == TyTy::TypeKind::BOOL)
|| (negated_expr_ty->get_kind () == TyTy::TypeKind::INT)
- || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT);
+ || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT)
+ || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER
+ && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind ()
+ == TyTy::InferType::INTEGRAL));
if (!valid)
{
rust_error_at (expr.get_locus (), "cannot apply unary ! to %s",
@@ -492,7 +554,8 @@ public:
break;
}
- infered = negated_expr_ty;
+ infered = negated_expr_ty->clone ();
+ infered->append_reference (negated_expr_ty->get_ref ());
}
void visit (HIR::IfExpr &expr)
@@ -567,23 +630,45 @@ public:
void visit (HIR::ArrayIndexExpr &expr)
{
- // FIXME this should be size type
- TyTy::IntType size_ty (expr.get_index_expr ()->get_mappings ().get_hirid (),
- TyTy::IntType::I32);
- auto resolved
- = size_ty.combine (TypeCheckExpr::Resolve (expr.get_index_expr ()));
- rust_assert (resolved != nullptr);
+ TyTy::TyBase *size_ty;
+ if (!context->lookup_builtin ("i32", &size_ty))
+ {
+ rust_error_at (
+ expr.get_locus (),
+ "Failure looking up size type for index in ArrayIndexExpr");
+ return;
+ }
+
+ auto resolved_index_expr
+ = size_ty->combine (TypeCheckExpr::Resolve (expr.get_index_expr ()));
+ if (resolved_index_expr == nullptr)
+ {
+ rust_error_at (expr.get_index_expr ()->get_locus_slow (),
+ "Type Resolver failure in Index for ArrayIndexExpr");
+ return;
+ }
+ context->insert_type (expr.get_index_expr ()->get_mappings (),
+ resolved_index_expr);
+ // resolve the array reference
expr.get_array_expr ()->accept_vis (*this);
- if (infered->get_kind () != TyTy::TypeKind::ARRAY)
+ if (infered == nullptr)
{
- rust_fatal_error (expr.get_array_expr ()->get_locus_slow (),
- "expected an ArrayType for index expression");
+ rust_error_at (expr.get_index_expr ()->get_locus_slow (),
+ "failed to resolve array reference expression");
+ return;
+ }
+ else if (infered->get_kind () != TyTy::TypeKind::ARRAY)
+ {
+ rust_error_at (expr.get_index_expr ()->get_locus_slow (),
+ "expected an ArrayType got [%s]",
+ infered->as_string ().c_str ());
+ infered = nullptr;
return;
}
- // extract the element type out now from the base type
- infered = TyTyExtractorArray::ExtractElementTypeFromArray (infered);
+ TyTy::ArrayType *array_type = (TyTy::ArrayType *) infered;
+ infered = array_type->get_type ()->clone ();
}
void visit (HIR::ArrayExpr &expr)
@@ -611,6 +696,9 @@ public:
{
infered_array_elems = infered_array_elems->combine (types.at (i));
}
+
+ for (auto &elem : types)
+ infered_array_elems->append_reference (elem->get_ref ());
}
void visit (HIR::ArrayElemsCopied &elems)
@@ -632,9 +720,12 @@ public:
{
auto struct_base
= TypeCheckExpr::Resolve (expr.get_receiver_expr ().get ());
- if (struct_base->get_kind () != TyTy::TypeKind::ADT)
+
+ bool is_valid_type = struct_base->get_kind () == TyTy::TypeKind::ADT;
+ if (!is_valid_type)
{
- rust_error_at (expr.get_locus (), "expected ADT Type got: [%s]",
+ rust_error_at (expr.get_locus (),
+ "expected ADT or Tuple Type got: [%s]",
struct_base->as_string ().c_str ());
return;
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h
index 566d43e..d7f9af1 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.h
@@ -24,43 +24,10 @@
#include "rust-hir-type-check-type.h"
#include "rust-hir-type-check-stmt.h"
#include "rust-tyty-visitor.h"
-#include "rust-tyty-resolver.h"
namespace Rust {
namespace Resolver {
-class ResolveFnType : public TyTy::TyVisitor
-{
-public:
- ResolveFnType (TyTy::TyBase *base) : base (base), state (nullptr) {}
-
- TyTy::TyBase *go ()
- {
- base->accept_vis (*this);
- if (state == nullptr)
- gcc_unreachable ();
-
- return state;
- }
-
- void visit (TyTy::UnitType &type) override { gcc_unreachable (); }
- void visit (TyTy::InferType &type) override { gcc_unreachable (); }
- void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); }
- void visit (TyTy::ADTType &type) override { gcc_unreachable (); }
- void visit (TyTy::ArrayType &type) override { gcc_unreachable (); }
- void visit (TyTy::BoolType &type) override { gcc_unreachable (); }
- void visit (TyTy::IntType &type) override { gcc_unreachable (); }
- void visit (TyTy::UintType &type) override { gcc_unreachable (); }
- void visit (TyTy::FloatType &type) override { gcc_unreachable (); }
- void visit (TyTy::ErrorType &type) override { gcc_unreachable (); }
-
- void visit (TyTy::FnType &type) override { state = type.return_type (); }
-
-private:
- TyTy::TyBase *base;
- TyTy::TyBase *state;
-};
-
class TypeCheckItem : public TypeCheckBase
{
public:
@@ -72,23 +39,42 @@ public:
void visit (HIR::Function &function)
{
- TyTy::TyBase *fnType;
- if (!context->lookup_type (function.get_mappings ().get_hirid (), &fnType))
+ TyTy::TyBase *lookup;
+ if (!context->lookup_type (function.get_mappings ().get_hirid (), &lookup))
{
rust_error_at (function.locus, "failed to lookup function type");
return;
}
+ if (lookup->get_kind () != TyTy::TypeKind::FNDEF)
+ {
+ rust_error_at (function.get_locus (),
+ "found invalid type for function [%s]",
+ lookup->as_string ().c_str ());
+ return;
+ }
+
// need to get the return type from this
- ResolveFnType resolve_fn_type (fnType);
- context->push_return_type (resolve_fn_type.go ());
+ TyTy::FnType *resolve_fn_type = (TyTy::FnType *) lookup;
+ auto expected_ret_tyty = resolve_fn_type->return_type ();
+ context->push_return_type (expected_ret_tyty);
TypeCheckExpr::Resolve (function.function_body.get ());
if (function.function_body->has_expr ())
{
auto resolved
= TypeCheckExpr::Resolve (function.function_body->expr.get ());
- context->peek_return_type ()->combine (resolved);
+
+ auto ret_resolved = expected_ret_tyty->combine (resolved);
+ if (ret_resolved == nullptr)
+ {
+ rust_error_at (function.function_body->expr->get_locus_slow (),
+ "failed to resolve final expression");
+ return;
+ }
+
+ context->peek_return_type ()->append_reference (
+ ret_resolved->get_ref ());
}
context->pop_return_type ();
diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
index e60c051..99be0b7 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
@@ -49,10 +49,19 @@ public:
void visit (HIR::LetStmt &stmt)
{
+ infered = new TyTy::UnitType (stmt.get_mappings ().get_hirid ());
+
TyTy::TyBase *init_expr_ty = nullptr;
if (stmt.has_init_expr ())
- init_expr_ty
- = TypeCheckExpr::Resolve (stmt.get_init_expr (), is_final_stmt);
+ {
+ init_expr_ty
+ = TypeCheckExpr::Resolve (stmt.get_init_expr (), is_final_stmt);
+
+ init_expr_ty = init_expr_ty->clone ();
+ auto ref = init_expr_ty->get_ref ();
+ init_expr_ty->set_ref (stmt.get_mappings ().get_hirid ());
+ init_expr_ty->append_reference (ref);
+ }
TyTy::TyBase *specified_ty = nullptr;
if (stmt.has_type ())
@@ -86,16 +95,17 @@ public:
// let x;
else
{
- context->insert_type (stmt.get_mappings (),
- new TyTy::InferType (
- stmt.get_mappings ().get_hirid ()));
+ context->insert_type (
+ stmt.get_mappings (),
+ new TyTy::InferType (stmt.get_mappings ().get_hirid (),
+ TyTy::InferType::InferTypeKind::GENERAL));
}
}
}
private:
TypeCheckStmt (bool is_final_stmt)
- : TypeCheckBase (), is_final_stmt (is_final_stmt)
+ : TypeCheckBase (), infered (nullptr), is_final_stmt (is_final_stmt)
{}
TyTy::TyBase *infered;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
index fcaf724..52b6cde 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
@@ -56,8 +56,7 @@ public:
TyTy::TyBase *type
= new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (),
- struct_decl.get_identifier (), true,
- std::move (fields));
+ struct_decl.get_identifier (), std::move (fields));
context->insert_type (struct_decl.get_mappings (), type);
}
@@ -78,8 +77,7 @@ public:
TyTy::TyBase *type
= new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (),
- struct_decl.get_identifier (), false,
- std::move (fields));
+ struct_decl.get_identifier (), std::move (fields));
context->insert_type (struct_decl.get_mappings (), type);
}
@@ -107,9 +105,15 @@ public:
ret_type = new TyTy::UnitType (function.get_mappings ().get_hirid ());
else
{
- TyTy::InferType infer (function.get_mappings ().get_hirid ());
auto resolved = TypeCheckType::Resolve (function.return_type.get ());
- ret_type = infer.combine (resolved);
+ if (resolved == nullptr)
+ {
+ rust_error_at (function.get_locus (),
+ "failed to resolve return type");
+ return;
+ }
+
+ ret_type = resolved->clone ();
ret_type->set_ref (function.return_type->get_mappings ().get_hirid ());
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h
index 579dfb0..e5d3898 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.h
@@ -40,11 +40,12 @@ public:
void visit (HIR::LiteralExpr &expr)
{
+ auto literal_value = expr.get_literal ();
switch (expr.get_lit_type ())
{
case HIR::Literal::LitType::INT: {
ok = true;
- std::stringstream ss (expr.as_string ());
+ std::stringstream ss (literal_value->as_string ());
ss >> result;
}
break;
@@ -70,8 +71,10 @@ public:
type->accept_vis (resolver);
if (resolver.translated != nullptr)
- resolver.context->insert_type (type->get_mappings (),
- resolver.translated);
+ {
+ resolver.context->insert_type (type->get_mappings (),
+ resolver.translated);
+ }
return resolver.translated;
}
@@ -89,25 +92,15 @@ public:
return;
}
- size_t index = 0;
- std::string identifier = "(";
- std::vector<TyTy::StructFieldType *> fields;
+ std::vector<HirId> fields;
for (auto &elem : tuple.get_elems ())
{
auto field_ty = TypeCheckType::Resolve (elem.get ());
- identifier += field_ty->as_string ();
- if ((index + 1) < tuple.get_elems ().size ())
- identifier += ",";
-
- auto field_tyty
- = new TyTy::StructFieldType (elem->get_mappings ().get_hirid (),
- std::to_string (index), field_ty);
- fields.push_back (field_tyty);
- index++;
+ fields.push_back (field_ty->get_ref ());
}
- identifier += ")";
- translated = new TyTy::ADTType (tuple.get_mappings ().get_hirid (),
- identifier, true, fields);
+
+ translated
+ = new TyTy::TupleType (tuple.get_mappings ().get_hirid (), fields);
}
void visit (HIR::TypePath &path)
@@ -129,6 +122,9 @@ public:
// we got an HIR node
if (context->lookup_type (hir_lookup, &translated))
{
+ translated = translated->clone ();
+ auto ref = path.get_mappings ().get_hirid ();
+ translated->set_ref (ref);
return;
}
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc
index aa3d505..cf3a846 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check.cc
@@ -34,6 +34,54 @@ TypeResolution::Resolve (HIR::Crate &crate)
for (auto it = crate.items.begin (); it != crate.items.end (); it++)
TypeCheckItem::Resolve (it->get ());
+
+ auto mappings = Analysis::Mappings::get ();
+ auto context = TypeCheckContext::get ();
+
+ context->iterate ([&] (HirId id, TyTy::TyBase *ty) mutable -> bool {
+ // nothing to do
+ if (ty->get_kind () != TyTy::TypeKind::INFER)
+ return true;
+
+ TyTy::InferType *infer_var = (TyTy::InferType *) ty;
+ switch (infer_var->get_infer_kind ())
+ {
+ case TyTy::InferType::GENERAL:
+ rust_error_at (mappings->lookup_location (id),
+ "unable to determine type: %u", id);
+ break;
+
+ case TyTy::InferType::INTEGRAL: {
+ TyTy::TyBase *default_integer;
+ bool ok = context->lookup_builtin ("i32", &default_integer);
+ rust_assert (ok);
+
+ auto result = ty->combine (default_integer);
+ result->set_ref (id);
+ context->insert_type (
+ Analysis::NodeMapping (mappings->get_current_crate (), 0, id,
+ UNKNOWN_LOCAL_DEFID),
+ result);
+ }
+ break;
+
+ case TyTy::InferType::FLOAT: {
+ TyTy::TyBase *default_float;
+ bool ok = context->lookup_builtin ("f32", &default_float);
+ rust_assert (ok);
+
+ auto result = ty->combine (default_float);
+ result->set_ref (id);
+ context->insert_type (
+ Analysis::NodeMapping (mappings->get_current_crate (), 0, id,
+ UNKNOWN_LOCAL_DEFID),
+ result);
+ }
+ break;
+ }
+
+ return true;
+ });
}
// RUST_HIR_TYPE_CHECK_EXPR
@@ -48,6 +96,12 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
bool is_final_expr = is_final_stmt && !expr.has_expr ();
auto infered = TypeCheckStmt::Resolve (s, is_final_expr);
+ if (infered == nullptr)
+ {
+ rust_error_at (s->get_locus_slow (), "failure to resolve type");
+ return false;
+ }
+
if (is_final_expr)
{
delete block_tyty;
@@ -59,21 +113,19 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
// tail expression must be checked as part of the caller since
// the result of this is very dependant on what we expect it to be
- if (expr.has_expr ())
- TypeCheckExpr::Resolve (expr.expr.get ());
// now that the stmts have been resolved we must resolve the block of locals
// and make sure the variables have been resolved
- auto body_mappings = expr.get_mappings ();
- Rib *rib = nullptr;
- if (!resolver->find_name_rib (body_mappings.get_nodeid (), &rib))
- {
- rust_fatal_error (expr.get_locus (), "failed to lookup locals per block");
- return;
- }
- TyTyResolver::Resolve (rib, mappings, resolver, context);
-
- infered = block_tyty;
+ // auto body_mappings = expr.get_mappings ();
+ // Rib *rib = nullptr;
+ // if (!resolver->find_name_rib (body_mappings.get_nodeid (), &rib))
+ // {
+ // rust_fatal_error (expr.get_locus (), "failed to lookup locals per
+ // block"); return;
+ // }
+ // TyTyResolver::Resolve (rib, mappings, resolver, context);
+
+ infered = block_tyty->clone ();
}
// RUST_HIR_TYPE_CHECK_STRUCT_FIELD
@@ -154,47 +206,23 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr)
= struct_expr.struct_base->base_struct->clone_expr_impl ();
HIR::StructExprField *implicit_field = nullptr;
- if (struct_path_resolved->is_tuple_struct ())
- {
- std::vector<HIR::Attribute> outer_attribs;
- TupleIndex tuple_index = std::stoi (missing);
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (
- crate_num,
- struct_expr.struct_base->base_struct->get_mappings ()
- .get_nodeid (),
- mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID);
-
- HIR::Expr *field_value = new HIR::TupleIndexExpr (
- mapping, std::unique_ptr<HIR::Expr> (receiver), tuple_index,
- std::move (outer_attribs),
- struct_expr.struct_base->base_struct->get_locus_slow ());
-
- implicit_field = new HIR::StructExprFieldIndexValue (
- mapping, tuple_index,
- std::unique_ptr<HIR::Expr> (field_value),
- struct_expr.struct_base->base_struct->get_locus_slow ());
- }
- else
- {
- std::vector<HIR::Attribute> outer_attribs;
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (
- crate_num,
- struct_expr.struct_base->base_struct->get_mappings ()
- .get_nodeid (),
- mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID);
-
- HIR::Expr *field_value = new HIR::FieldAccessExpr (
- mapping, std::unique_ptr<HIR::Expr> (receiver), missing,
- std::move (outer_attribs),
- struct_expr.struct_base->base_struct->get_locus_slow ());
-
- implicit_field = new HIR::StructExprFieldIdentifierValue (
- mapping, missing, std::unique_ptr<HIR::Expr> (field_value),
- struct_expr.struct_base->base_struct->get_locus_slow ());
- }
+
+ std::vector<HIR::Attribute> outer_attribs;
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (
+ crate_num,
+ struct_expr.struct_base->base_struct->get_mappings ()
+ .get_nodeid (),
+ mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID);
+
+ HIR::Expr *field_value = new HIR::FieldAccessExpr (
+ mapping, std::unique_ptr<HIR::Expr> (receiver), missing,
+ std::move (outer_attribs),
+ struct_expr.struct_base->base_struct->get_locus_slow ());
+
+ implicit_field = new HIR::StructExprFieldIdentifierValue (
+ mapping, missing, std::unique_ptr<HIR::Expr> (field_value),
+ struct_expr.struct_base->base_struct->get_locus_slow ());
size_t field_index;
bool ok = struct_path_resolved->get_field (missing, &field_index);
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index e0458a7..d033878 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -47,6 +47,15 @@ public:
void push_return_type (TyTy::TyBase *return_type);
void pop_return_type ();
+ void iterate (std::function<bool (HirId, TyTy::TyBase *)> cb)
+ {
+ for (auto it = resolved.begin (); it != resolved.end (); it++)
+ {
+ if (!cb (it->first, it->second))
+ return;
+ }
+ }
+
private:
TypeCheckContext ();
diff --git a/gcc/rust/typecheck/rust-tycheck-dump.h b/gcc/rust/typecheck/rust-tycheck-dump.h
new file mode 100644
index 0000000..863c2eb
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tycheck-dump.h
@@ -0,0 +1,178 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_TYCHECK_DUMP
+#define RUST_TYCHECK_DUMP
+
+#include "rust-hir-type-check-base.h"
+#include "rust-hir-full.h"
+
+namespace Rust {
+namespace Resolver {
+
+class TypeResolverDump : public TypeCheckBase
+{
+public:
+ static std::string go (HIR::Crate &crate)
+ {
+ TypeResolverDump dumper;
+ for (auto &item : crate.items)
+ item->accept_vis (dumper);
+
+ return dumper.dump;
+ }
+
+ void visit (HIR::Function &function)
+ {
+ dump += indent () + "fn " + function.function_name + " "
+ + type_string (function.get_mappings ()) + "\n";
+ dump += indent () + "{\n";
+
+ HIR::BlockExpr *function_body = function.function_body.get ();
+ function_body->accept_vis (*this);
+
+ dump += indent () + "}\n";
+ }
+
+ void visit (HIR::BlockExpr &expr)
+ {
+ indentation_level++;
+
+ expr.iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool {
+ s->accept_vis (*this);
+ dump += ";\n";
+ return true;
+ });
+
+ if (expr.has_expr () && expr.tail_expr_reachable ())
+ {
+ expr.expr->accept_vis (*this);
+ dump += ";\n";
+ }
+
+ indentation_level--;
+ }
+
+ void visit (HIR::LetStmt &stmt)
+ {
+ dump += indent () + "let " + stmt.get_pattern ()->as_string () + ":"
+ + type_string (stmt.get_mappings ());
+ if (stmt.has_init_expr ())
+ {
+ dump += " = ";
+ stmt.get_init_expr ()->accept_vis (*this);
+ }
+ }
+
+ void visit (HIR::ExprStmtWithBlock &stmt)
+ {
+ dump += indent ();
+ stmt.get_expr ()->accept_vis (*this);
+ }
+
+ void visit (HIR::ExprStmtWithoutBlock &stmt)
+ {
+ dump += indent ();
+ stmt.get_expr ()->accept_vis (*this);
+ }
+
+ void visit (HIR::AssignmentExpr &expr)
+ {
+ expr.get_lhs ()->accept_vis (*this);
+ dump += " = ";
+ expr.get_rhs ()->accept_vis (*this);
+ }
+
+ void visit (HIR::LiteralExpr &expr)
+ {
+ dump += expr.get_literal ()->as_string () + ":"
+ + type_string (expr.get_mappings ());
+ }
+
+ void visit (HIR::IdentifierExpr &expr)
+ {
+ dump += expr.get_identifier () + ":" + type_string (expr.get_mappings ());
+ }
+
+ void visit (HIR::ArrayExpr &expr)
+ {
+ dump += type_string (expr.get_mappings ()) + ":[";
+
+ HIR::ArrayElems *elements = expr.get_internal_elements ();
+ elements->accept_vis (*this);
+
+ dump += "]";
+ }
+
+ void visit (HIR::ArrayElemsValues &elems)
+ {
+ elems.iterate ([&] (HIR::Expr *e) mutable -> bool {
+ e->accept_vis (*this);
+ dump += ",";
+ return true;
+ });
+ }
+
+ void visit (HIR::GroupedExpr &expr)
+ {
+ HIR::Expr *paren_expr = expr.get_expr_in_parens ().get ();
+ dump += "(";
+ paren_expr->accept_vis (*this);
+ dump += ")";
+ }
+
+protected:
+ std::string type_string (const Analysis::NodeMapping &mappings)
+ {
+ TyTy::TyBase *lookup = nullptr;
+ if (!context->lookup_type (mappings.get_hirid (), &lookup))
+ return "<error>";
+
+ std::string buf = "[";
+ for (auto &ref : lookup->get_combined_refs ())
+ {
+ buf += std::to_string (ref);
+ buf += ", ";
+ }
+ buf += "]";
+
+ return "<" + lookup->as_string ()
+ + " RF:" + std::to_string (lookup->get_ref ()) + " TF:"
+ + std::to_string (lookup->get_ty_ref ()) + +" - " + buf + ">";
+ }
+
+ std::string indent ()
+ {
+ std::string buf;
+ for (size_t i = 0; i < indentation_level; ++i)
+ buf += " ";
+
+ return buf;
+ }
+
+private:
+ TypeResolverDump () : TypeCheckBase (), indentation_level (0) {}
+
+ std::string dump;
+ size_t indentation_level;
+};
+
+} // namespace Resolver
+} // namespace Rust
+
+#endif // RUST_TYCHECK_DUMP
diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h
index 2e98cbb..84cfdce 100644
--- a/gcc/rust/typecheck/rust-tyty-call.h
+++ b/gcc/rust/typecheck/rust-tyty-call.h
@@ -23,6 +23,7 @@
#include "rust-hir-full.h"
#include "rust-tyty-visitor.h"
#include "rust-tyty.h"
+#include "rust-hir-type-check.h"
namespace Rust {
namespace TyTy {
@@ -30,9 +31,10 @@ namespace TyTy {
class TypeCheckCallExpr : private TyVisitor
{
public:
- static TyBase *go (TyBase *ref, HIR::CallExpr &call)
+ static TyBase *go (TyBase *ref, HIR::CallExpr &call,
+ Resolver::TypeCheckContext *context)
{
- TypeCheckCallExpr checker (call);
+ TypeCheckCallExpr checker (call, context);
ref->accept_vis (checker);
return checker.resolved;
}
@@ -40,6 +42,7 @@ public:
void visit (UnitType &type) override { gcc_unreachable (); }
void visit (InferType &type) override { gcc_unreachable (); }
+ void visit (TupleType &type) override { gcc_unreachable (); }
void visit (StructFieldType &type) override { gcc_unreachable (); }
void visit (ArrayType &type) override { gcc_unreachable (); }
void visit (BoolType &type) override { gcc_unreachable (); }
@@ -55,10 +58,15 @@ public:
void visit (FnType &type) override;
private:
- TypeCheckCallExpr (HIR::CallExpr &c) : resolved (nullptr), call (c) {}
+ TypeCheckCallExpr (HIR::CallExpr &c, Resolver::TypeCheckContext *context)
+ : resolved (nullptr), call (c), context (context),
+ mappings (Analysis::Mappings::get ())
+ {}
TyBase *resolved;
HIR::CallExpr &call;
+ Resolver::TypeCheckContext *context;
+ Analysis::Mappings *mappings;
};
} // namespace TyTy
diff --git a/gcc/rust/typecheck/rust-tyty-resolver.h b/gcc/rust/typecheck/rust-tyty-resolver.h
deleted file mode 100644
index d48952c..0000000
--- a/gcc/rust/typecheck/rust-tyty-resolver.h
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright (C) 2020 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_TYTY_RESOLVER
-#define RUST_TYTY_RESOLVER
-
-#include "rust-system.h"
-#include "rust-diagnostics.h"
-#include "rust-hir-map.h"
-#include "rust-name-resolver.h"
-#include "rust-hir-type-check.h"
-#include "rust-hir-full.h"
-#include "rust-tyty-visitor.h"
-
-namespace Rust {
-namespace Resolver {
-
-class TyTyResolver
-{
-public:
- static void Resolve (Rib *rib, Analysis::Mappings *mappings,
- Resolver *resolver, TypeCheckContext *context)
- {
- TyTyResolver r (mappings, resolver, context);
- r.go (rib);
- }
-
- virtual ~TyTyResolver () {}
-
- void go (Rib *rib)
- {
- rib->iterate_decls ([&] (NodeId decl_node_id,
- Location locus) mutable -> bool {
- // type inference in rust means we need to gather and examine all
- // references of this decl and combine each to make sure the type is
- // correctly inferred. Consider the example:
- // let mut x; x = 1;
- // we can only say x is an infer variable then at the assignment
- // we think x must be an integer
-
- bool ok = true;
- std::vector<TyTy::TyBase *> gathered_types;
- rib->iterate_references_for_def (
- decl_node_id, [&] (NodeId ref_node) mutable -> bool {
- HirId hir_node_ref;
- if (!mappings->lookup_node_to_hir (mappings->get_current_crate (),
- ref_node, &hir_node_ref))
- {
- rust_error_at (locus,
- "failed to reserve lookup HIR node for reference");
- ok = false;
- return false;
- }
-
- TyTy::TyBase *resolved = nullptr;
- if (!context->lookup_type (hir_node_ref, &resolved))
- {
- // this could be an array/adt type
- Definition d;
- if (!resolver->lookup_definition (ref_node, &d))
- {
- rust_error_at (
- locus,
- "failed to lookup definition for referenced hir node");
-
- ok = false;
- return false;
- }
-
- if (!mappings->lookup_node_to_hir (mappings->get_current_crate (),
- d.parent, &hir_node_ref))
- {
- rust_error_at (locus,
- "failed to lookup HIR node for parent NodeId");
-
- ok = false;
- return false;
- }
-
- if (!context->lookup_type (hir_node_ref, &resolved))
- {
- rust_error_at (
- mappings->lookup_location (hir_node_ref),
- "failed to lookup type for reference at node [%u]",
- hir_node_ref);
-
- ok = false;
- return false;
- }
- }
-
- gathered_types.push_back (resolved);
- return true;
- });
-
- Definition d;
- if (!resolver->lookup_definition (decl_node_id, &d))
- {
- rust_error_at (locus, "Failed to lookup definition within rib");
- return false;
- }
-
- HIR::Stmt *decl = nullptr;
- if (!mappings->resolve_nodeid_to_stmt (d.parent, &decl))
- {
- rust_error_at (locus, "Failed to resolve decl to HIR::Stmt");
- return false;
- }
-
- TyTy::TyBase *resolved_type = nullptr;
- if (!context->lookup_type (decl->get_mappings ().get_hirid (),
- &resolved_type))
- {
- rust_error_at (locus, "Unknown base type for decl in Rib");
- return false;
- }
-
- // if it is not infer then it must have been figured out already
- // we might need changes for generics later on
- if (resolved_type->get_kind () != TyTy::TypeKind::INFER)
- return true;
-
- auto resolved_tyty = resolved_type;
- for (auto it : gathered_types)
- {
- auto combined = resolved_tyty->combine (it);
- if (combined == nullptr)
- {
- rust_fatal_error (decl->get_locus_slow (),
- "type-check resolver failed");
- break;
- }
-
- resolved_tyty = combined;
- }
-
- // something is not inferred we need to look at all references now
- if (resolved_tyty == nullptr
- || resolved_tyty->get_kind () == TyTy::TypeKind::INFER
- || resolved_tyty->get_kind () == TyTy::TypeKind::ERROR)
- {
- rust_fatal_error (decl->get_locus_slow (), "failed to resolve type");
- return false;
- }
-
- // insert the new resolved definition
- context->insert_type (decl->get_mappings (), resolved_tyty);
- return true;
- });
- }
-
-protected:
-private:
- TyTyResolver (Analysis::Mappings *mappings, Resolver *resolver,
- TypeCheckContext *context)
- : mappings (mappings), resolver (resolver), context (context)
- {}
-
- Analysis::Mappings *mappings;
- Resolver *resolver;
- TypeCheckContext *context;
-};
-
-class TyTyExtractorArray : public TyTy::TyVisitor
-{
-public:
- static TyTy::TyBase *ExtractElementTypeFromArray (TyTy::TyBase *base)
- {
- TyTyExtractorArray e;
- base->accept_vis (e);
- rust_assert (e.extracted != nullptr);
- return e.extracted;
- }
-
- virtual ~TyTyExtractorArray () {}
-
- void visit (TyTy::UnitType &type) override { gcc_unreachable (); }
- void visit (TyTy::InferType &type) override { gcc_unreachable (); }
- void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); }
- void visit (TyTy::ADTType &type) override { gcc_unreachable (); }
- void visit (TyTy::FnType &type) override { gcc_unreachable (); }
- void visit (TyTy::BoolType &type) override { gcc_unreachable (); }
- void visit (TyTy::IntType &type) override { gcc_unreachable (); }
- void visit (TyTy::UintType &type) override { gcc_unreachable (); }
- void visit (TyTy::FloatType &type) override { gcc_unreachable (); }
- void visit (TyTy::ErrorType &type) override { gcc_unreachable (); }
-
- void visit (TyTy::ArrayType &type) override { extracted = type.get_type (); }
-
-private:
- TyTyExtractorArray () : extracted (nullptr) {}
-
- TyTy::TyBase *extracted;
-};
-
-} // namespace Resolver
-} // namespace Rust
-
-#endif // RUST_TYTY_RESOLVER
diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h
index 241b9be..890931f 100644
--- a/gcc/rust/typecheck/rust-tyty-rules.h
+++ b/gcc/rust/typecheck/rust-tyty-rules.h
@@ -23,6 +23,7 @@
#include "rust-tyty.h"
#include "rust-tyty-visitor.h"
#include "rust-hir-map.h"
+#include "rust-hir-type-check.h"
namespace Rust {
namespace TyTy {
@@ -32,161 +33,306 @@ class BaseRules : public TyVisitor
public:
virtual ~BaseRules () {}
+ TyBase *combine (TyBase *other)
+ {
+ other->accept_vis (*this);
+ if (resolved != nullptr)
+ {
+ resolved->append_reference (base->get_ref ());
+ resolved->append_reference (other->get_ref ());
+ for (auto ref : base->get_combined_refs ())
+ resolved->append_reference (ref);
+ for (auto ref : other->get_combined_refs ())
+ resolved->append_reference (ref);
+
+ bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER;
+ if (result_resolved)
+ {
+ for (auto &ref : resolved->get_combined_refs ())
+ {
+ TyTy::TyBase *ref_tyty = nullptr;
+ bool ok = context->lookup_type (ref, &ref_tyty);
+ if (!ok)
+ continue;
+
+ // if any of the types are inference variables lets fix them
+ if (ref_tyty->get_kind () == TyTy::TypeKind::INFER)
+ {
+ NodeId ref_node_id = UNKNOWN_NODEID;
+ context->insert_type (
+ Analysis::NodeMapping (mappings->get_current_crate (),
+ ref_node_id, ref,
+ UNKNOWN_LOCAL_DEFID),
+ resolved->clone ());
+ }
+ }
+ }
+ }
+ return resolved;
+ }
+
virtual void visit (UnitType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_error_at (def_locus, "declared here");
+ }
+
+ virtual void visit (TupleType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ rust_error_at (ref_locus, "expected [%s] got [%s]",
+ base->as_string ().c_str (), type.as_string ().c_str ());
}
virtual void visit (ADTType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_error_at (def_locus, "declared here");
}
virtual void visit (InferType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_error_at (def_locus, "declared here");
}
virtual void visit (FnType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_error_at (def_locus, "declared here");
}
virtual void visit (ArrayType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_error_at (def_locus, "declared here");
}
virtual void visit (BoolType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_error_at (def_locus, "declared here");
}
virtual void visit (IntType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_error_at (def_locus, "declared here");
}
virtual void visit (UintType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_error_at (def_locus, "declared here");
}
virtual void visit (FloatType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_error_at (def_locus, "declared here");
}
virtual void visit (ErrorType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_error_at (def_locus, "declared here");
}
virtual void visit (StructFieldType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_error_at (def_locus, "declared here");
}
protected:
BaseRules (TyBase *base)
- : mappings (Analysis::Mappings::get ()), base (base),
+ : mappings (Analysis::Mappings::get ()),
+ context (Resolver::TypeCheckContext::get ()), base (base),
resolved (new ErrorType (base->get_ref (), base->get_ref ()))
{}
Analysis::Mappings *mappings;
+ Resolver::TypeCheckContext *context;
+
TyBase *base;
TyBase *resolved;
};
-class InferRules : protected BaseRules
+class InferRules : public BaseRules
{
public:
InferRules (InferType *base) : BaseRules (base), base (base) {}
- TyBase *combine (TyBase *other)
+ void visit (UnitType &type) override
{
- other->accept_vis (*this);
- return resolved;
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseRules::visit (type);
+ }
+
+ void visit (BoolType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseRules::visit (type);
+ }
+
+ void visit (IntType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
+ || (base->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::INTEGRAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseRules::visit (type);
+ }
+
+ void visit (UintType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
+ || (base->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::INTEGRAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseRules::visit (type);
+ }
+
+ void visit (FloatType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
+ || (base->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseRules::visit (type);
}
- // we are an inference variable so this means we can take the other as the
- // type
- void visit (InferType &type) override { resolved = type.clone (); }
+ void visit (ArrayType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseRules::visit (type);
+ }
- void visit (UnitType &type) override { resolved = type.clone (); }
+ void visit (ADTType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
- void visit (BoolType &type) override { resolved = type.clone (); }
+ BaseRules::visit (type);
+ }
- void visit (IntType &type) override { resolved = type.clone (); }
+ void visit (TupleType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
- void visit (UintType &type) override { resolved = type.clone (); }
+ BaseRules::visit (type);
+ }
- void visit (FloatType &type) override { resolved = type.clone (); }
+ void visit (InferType &type) override
+ {
+ switch (base->get_infer_kind ())
+ {
+ case InferType::InferTypeKind::GENERAL:
+ resolved = type.clone ();
+ return;
- void visit (ArrayType &type) override { resolved = type.clone (); }
+ case InferType::InferTypeKind::INTEGRAL: {
+ if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL)
+ {
+ resolved = type.clone ();
+ return;
+ }
+ else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL)
+ {
+ resolved = base->clone ();
+ return;
+ }
+ }
+ break;
+
+ case InferType::InferTypeKind::FLOAT: {
+ if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
+ {
+ resolved = type.clone ();
+ return;
+ }
+ else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL)
+ {
+ resolved = base->clone ();
+ return;
+ }
+ }
+ break;
+ }
- void visit (ADTType &type) override { resolved = type.clone (); }
+ BaseRules::visit (type);
+ }
private:
InferType *base;
};
-class StructFieldTypeRules : protected BaseRules
+class StructFieldTypeRules : public BaseRules
{
public:
StructFieldTypeRules (StructFieldType *base) : BaseRules (base), base (base)
{}
- TyBase *combine (TyBase *other)
- {
- other->accept_vis (*this);
- return resolved;
- }
-
void visit (StructFieldType &type)
{
TyBase *ty = base->get_field_type ()->combine (type.get_field_type ());
@@ -201,17 +347,11 @@ private:
StructFieldType *base;
};
-class UnitRules : protected BaseRules
+class UnitRules : public BaseRules
{
public:
UnitRules (UnitType *base) : BaseRules (base), base (base) {}
- TyBase *combine (TyBase *other)
- {
- other->accept_vis (*this);
- return resolved;
- }
-
void visit (UnitType &type) override
{
resolved = new UnitType (type.get_ref (), type.get_ty_ref ());
@@ -221,44 +361,36 @@ private:
UnitType *base;
};
-class FnRules : protected BaseRules
+class FnRules : public BaseRules
{
public:
FnRules (FnType *base) : BaseRules (base), base (base) {}
- TyBase *combine (TyBase *other)
- {
- other->accept_vis (*this);
- return resolved;
- }
-
private:
FnType *base;
};
-class ArrayRules : protected BaseRules
+class ArrayRules : public BaseRules
{
public:
ArrayRules (ArrayType *base) : BaseRules (base), base (base) {}
- TyBase *combine (TyBase *other)
- {
- other->accept_vis (*this);
- return resolved;
- }
-
void visit (ArrayType &type) override
{
// check base type
auto base_resolved = base->get_type ()->combine (type.get_type ());
if (base_resolved == nullptr)
- return;
+ {
+ // fixme add error message
+ return;
+ }
// need to check the base types and capacity
if (type.get_capacity () != base->get_capacity ())
{
Location locus = mappings->lookup_location (type.get_ref ());
rust_error_at (locus, "mismatch in array capacity");
+ BaseRules::visit (type);
return;
}
@@ -270,17 +402,11 @@ private:
ArrayType *base;
};
-class BoolRules : protected BaseRules
+class BoolRules : public BaseRules
{
public:
BoolRules (BoolType *base) : BaseRules (base), base (base) {}
- TyBase *combine (TyBase *other)
- {
- other->accept_vis (*this);
- return resolved;
- }
-
void visit (BoolType &type) override
{
resolved = new BoolType (type.get_ref (), type.get_ty_ref ());
@@ -290,15 +416,22 @@ private:
BoolType *base;
};
-class IntRules : protected BaseRules
+class IntRules : public BaseRules
{
public:
IntRules (IntType *base) : BaseRules (base), base (base) {}
- TyBase *combine (TyBase *other)
+ void visit (InferType &type) override
{
- other->accept_vis (*this);
- return resolved;
+ // cant assign a float inference variable
+ if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
}
void visit (IntType &type) override
@@ -317,15 +450,22 @@ private:
IntType *base;
};
-class UintRules : protected BaseRules
+class UintRules : public BaseRules
{
public:
UintRules (UintType *base) : BaseRules (base), base (base) {}
- TyBase *combine (TyBase *other)
+ void visit (InferType &type) override
{
- other->accept_vis (*this);
- return resolved;
+ // cant assign a float inference variable
+ if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
}
void visit (UintType &type) override
@@ -344,15 +484,21 @@ private:
UintType *base;
};
-class FloatRules : protected BaseRules
+class FloatRules : public BaseRules
{
public:
FloatRules (FloatType *base) : BaseRules (base), base (base) {}
- TyBase *combine (TyBase *other)
+ void visit (InferType &type) override
{
- other->accept_vis (*this);
- return resolved;
+ if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
}
void visit (FloatType &type) override
@@ -371,17 +517,11 @@ private:
FloatType *base;
};
-class ADTRules : protected BaseRules
+class ADTRules : public BaseRules
{
public:
ADTRules (ADTType *base) : BaseRules (base), base (base) {}
- TyBase *combine (TyBase *other)
- {
- other->accept_vis (*this);
- return resolved;
- }
-
void visit (ADTType &type)
{
if (base->num_fields () != type.num_fields ())
@@ -390,12 +530,6 @@ public:
return;
}
- if (base->get_name ().compare (type.get_name ()) != 0)
- {
- BaseRules::visit (type);
- return;
- }
-
std::vector<TyTy::StructFieldType *> fields;
for (size_t i = 0; i < type.num_fields (); ++i)
{
@@ -412,15 +546,51 @@ public:
fields.push_back ((TyTy::StructFieldType *) combined);
}
- resolved
- = new TyTy::ADTType (type.get_ref (), type.get_ty_ref (),
- type.get_name (), type.is_tuple_struct (), fields);
+ resolved = new TyTy::ADTType (type.get_ref (), type.get_ty_ref (),
+ type.get_name (), fields);
}
private:
ADTType *base;
};
+class TupleRules : public BaseRules
+{
+public:
+ TupleRules (TupleType *base) : BaseRules (base), base (base) {}
+
+ void visit (TupleType &type)
+ {
+ if (base->num_fields () != type.num_fields ())
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ std::vector<HirId> fields;
+ for (size_t i = 0; i < base->num_fields (); i++)
+ {
+ TyBase *bo = base->get_field (i);
+ TyBase *fo = type.get_field (i);
+
+ TyBase *combined = bo->combine (fo);
+ if (combined == nullptr)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ fields.push_back (combined->get_ref ());
+ }
+
+ resolved
+ = new TyTy::TupleType (type.get_ref (), type.get_ty_ref (), fields);
+ }
+
+private:
+ TupleType *base;
+};
+
} // namespace TyTy
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h
index b6759dd..3997295 100644
--- a/gcc/rust/typecheck/rust-tyty-visitor.h
+++ b/gcc/rust/typecheck/rust-tyty-visitor.h
@@ -31,6 +31,7 @@ public:
virtual void visit (InferType &type) = 0;
virtual void visit (StructFieldType &type) = 0;
virtual void visit (ADTType &type) = 0;
+ virtual void visit (TupleType &type) = 0;
virtual void visit (FnType &type) = 0;
virtual void visit (ArrayType &type) = 0;
virtual void visit (BoolType &type) = 0;
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 2e09de6..9efde68 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -47,7 +47,7 @@ UnitType::combine (TyBase *other)
TyBase *
UnitType::clone ()
{
- return new UnitType (get_ref (), get_ty_ref ());
+ return new UnitType (get_ref (), get_ty_ref (), get_combined_refs ());
}
void
@@ -59,7 +59,16 @@ InferType::accept_vis (TyVisitor &vis)
std::string
InferType::as_string () const
{
- return "?";
+ switch (infer_kind)
+ {
+ case GENERAL:
+ return "T?";
+ case INTEGRAL:
+ return "<integer>";
+ case FLOAT:
+ return "<float>";
+ }
+ return "<infer::error>";
}
TyBase *
@@ -72,7 +81,8 @@ InferType::combine (TyBase *other)
TyBase *
InferType::clone ()
{
- return new InferType (get_ref (), get_ty_ref ());
+ return new InferType (get_ref (), get_ty_ref (), get_infer_kind (),
+ get_combined_refs ());
}
void
@@ -98,7 +108,7 @@ ErrorType::combine (TyBase *other)
TyBase *
ErrorType::clone ()
{
- return new ErrorType (get_ref ());
+ return new ErrorType (get_ref (), get_ty_ref (), get_combined_refs ());
}
void
@@ -124,7 +134,8 @@ TyBase *
StructFieldType::clone ()
{
return new StructFieldType (get_ref (), get_ty_ref (), get_name (),
- get_field_type ()->clone ());
+ get_field_type ()->clone (),
+ get_combined_refs ());
}
void
@@ -157,8 +168,50 @@ ADTType::clone ()
for (auto &f : fields)
cloned_fields.push_back ((StructFieldType *) f->clone ());
- return new ADTType (get_ref (), get_ty_ref (), get_name (),
- is_tuple_struct (), cloned_fields);
+ return new ADTType (get_ref (), get_ty_ref (), get_name (), cloned_fields,
+ get_combined_refs ());
+}
+
+void
+TupleType::accept_vis (TyVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+std::string
+TupleType::as_string () const
+{
+ std::string fields_buffer;
+ iterate_fields ([&] (TyBase *field) mutable -> bool {
+ fields_buffer += field->as_string ();
+ fields_buffer += ", ";
+ return true;
+ });
+ return "(" + fields_buffer + ")";
+}
+
+TyBase *
+TupleType::get_field (size_t index) const
+{
+ auto context = Resolver::TypeCheckContext::get ();
+ TyBase *lookup = nullptr;
+ bool ok = context->lookup_type (fields.at (index), &lookup);
+ rust_assert (ok);
+ return lookup;
+}
+
+TyBase *
+TupleType::combine (TyBase *other)
+{
+ TupleRules r (this);
+ return r.combine (other);
+}
+
+TyBase *
+TupleType::clone ()
+{
+ return new TupleType (get_ref (), get_ty_ref (), fields,
+ get_combined_refs ());
}
void
@@ -199,7 +252,7 @@ FnType::clone ()
std::pair<HIR::Pattern *, TyBase *> (p.first, p.second->clone ()));
return new FnType (get_ref (), get_ty_ref (), cloned_params,
- get_return_type ()->clone ());
+ get_return_type ()->clone (), get_combined_refs ());
}
void
@@ -211,7 +264,8 @@ ArrayType::accept_vis (TyVisitor &vis)
std::string
ArrayType::as_string () const
{
- return "[" + type->as_string () + ":" + std::to_string (capacity) + "]";
+ return "[" + get_type ()->as_string () + ":" + std::to_string (capacity)
+ + "]";
}
TyBase *
@@ -222,10 +276,20 @@ ArrayType::combine (TyBase *other)
}
TyBase *
+ArrayType::get_type () const
+{
+ auto context = Resolver::TypeCheckContext::get ();
+ TyBase *lookup = nullptr;
+ bool ok = context->lookup_type (element_type_id, &lookup);
+ rust_assert (ok);
+ return lookup;
+}
+
+TyBase *
ArrayType::clone ()
{
return new ArrayType (get_ref (), get_ty_ref (), get_capacity (),
- get_type ()->clone ());
+ get_type ()->clone (), get_combined_refs ());
}
void
@@ -250,7 +314,7 @@ BoolType::combine (TyBase *other)
TyBase *
BoolType::clone ()
{
- return new BoolType (get_ref (), get_ty_ref ());
+ return new BoolType (get_ref (), get_ty_ref (), get_combined_refs ());
}
void
@@ -289,7 +353,8 @@ IntType::combine (TyBase *other)
TyBase *
IntType::clone ()
{
- return new IntType (get_ref (), get_ty_ref (), get_kind ());
+ return new IntType (get_ref (), get_ty_ref (), get_kind (),
+ get_combined_refs ());
}
void
@@ -328,7 +393,8 @@ UintType::combine (TyBase *other)
TyBase *
UintType::clone ()
{
- return new UintType (get_ref (), get_ty_ref (), get_kind ());
+ return new UintType (get_ref (), get_ty_ref (), get_kind (),
+ get_combined_refs ());
}
void
@@ -361,18 +427,13 @@ FloatType::combine (TyBase *other)
TyBase *
FloatType::clone ()
{
- return new FloatType (get_ref (), get_ty_ref (), get_kind ());
+ return new FloatType (get_ref (), get_ty_ref (), get_kind (),
+ get_combined_refs ());
}
void
TypeCheckCallExpr::visit (ADTType &type)
{
- if (!type.is_tuple_struct ())
- {
- rust_error_at (call.get_locus (), "Expected TupleStruct");
- return;
- }
-
if (call.num_params () != type.num_fields ())
{
rust_error_at (call.get_locus (),
@@ -425,21 +486,26 @@ TypeCheckCallExpr::visit (FnType &type)
}
size_t i = 0;
- call.iterate_params ([&] (HIR::Expr *p) mutable -> bool {
+ call.iterate_params ([&] (HIR::Expr *param) mutable -> bool {
auto fnparam = type.param_at (i);
- auto t = Resolver::TypeCheckExpr::Resolve (p);
- if (t == nullptr)
+ auto argument_expr_tyty = Resolver::TypeCheckExpr::Resolve (param);
+ if (argument_expr_tyty == nullptr)
{
- rust_error_at (p->get_locus_slow (), "failed to resolve type");
+ rust_error_at (param->get_locus_slow (),
+ "failed to resolve type for argument expr in CallExpr");
return false;
}
- auto pt = fnparam.second;
- auto res = pt->combine (t);
- if (res == nullptr)
- return false;
+ auto resolved_argument_type = fnparam.second->combine (argument_expr_tyty);
+ if (resolved_argument_type == nullptr)
+ {
+ rust_error_at (param->get_locus_slow (),
+ "Type Resolution failure on parameter");
+ return false;
+ }
+
+ context->insert_type (param->get_mappings (), resolved_argument_type);
- delete res;
i++;
return true;
});
@@ -452,7 +518,7 @@ TypeCheckCallExpr::visit (FnType &type)
return;
}
- resolved = type.get_return_type ();
+ resolved = type.get_return_type ()->clone ();
}
} // namespace TyTy
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index a73a344..6c6f27c 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -24,6 +24,7 @@
namespace Rust {
namespace TyTy {
+// https://rustc-dev-guide.rust-lang.org/type-inference.html#inference-variables
// https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variants
enum TypeKind
{
@@ -72,22 +73,42 @@ public:
virtual TyBase *clone () = 0;
+ std::set<HirId> get_combined_refs () { return combined; }
+
+ void append_reference (HirId id) { combined.insert (id); }
+
protected:
- TyBase (HirId ref, HirId ty_ref, TypeKind kind)
- : kind (kind), ref (ref), ty_ref (ty_ref)
+ TyBase (HirId ref, HirId ty_ref, TypeKind kind,
+ std::set<HirId> refs = std::set<HirId> ())
+ : kind (kind), ref (ref), ty_ref (ty_ref), combined (refs)
{}
TypeKind kind;
HirId ref;
HirId ty_ref;
+
+ std::set<HirId> combined;
};
class InferType : public TyBase
{
public:
- InferType (HirId ref) : TyBase (ref, ref, TypeKind::INFER) {}
+ enum InferTypeKind
+ {
+ GENERAL,
+ INTEGRAL,
+ FLOAT
+ };
+
+ InferType (HirId ref, InferTypeKind infer_kind,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::INFER, refs), infer_kind (infer_kind)
+ {}
- InferType (HirId ref, HirId ty_ref) : TyBase (ref, ty_ref, TypeKind::INFER) {}
+ InferType (HirId ref, HirId ty_ref, InferTypeKind infer_kind,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::INFER, refs), infer_kind (infer_kind)
+ {}
void accept_vis (TyVisitor &vis) override;
@@ -98,14 +119,23 @@ public:
TyBase *combine (TyBase *other) override;
TyBase *clone () final override;
+
+ InferTypeKind get_infer_kind () const { return infer_kind; }
+
+private:
+ InferTypeKind infer_kind;
};
class ErrorType : public TyBase
{
public:
- ErrorType (HirId ref) : TyBase (ref, ref, TypeKind::ERROR) {}
+ ErrorType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::ERROR, refs)
+ {}
- ErrorType (HirId ref, HirId ty_ref) : TyBase (ref, ty_ref, TypeKind::ERROR) {}
+ ErrorType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::ERROR, refs)
+ {}
void accept_vis (TyVisitor &vis) override;
@@ -121,9 +151,13 @@ public:
class UnitType : public TyBase
{
public:
- UnitType (HirId ref) : TyBase (ref, ref, TypeKind::UNIT) {}
+ UnitType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::UNIT, refs)
+ {}
- UnitType (HirId ref, HirId ty_ref) : TyBase (ref, ty_ref, TypeKind::UNIT) {}
+ UnitType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::UNIT, refs)
+ {}
void accept_vis (TyVisitor &vis) override;
@@ -139,12 +173,14 @@ public:
class StructFieldType : public TyBase
{
public:
- StructFieldType (HirId ref, std::string name, TyBase *ty)
- : TyBase (ref, ref, TypeKind::FIELD), name (name), ty (ty)
+ StructFieldType (HirId ref, std::string name, TyBase *ty,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::FIELD, refs), name (name), ty (ty)
{}
- StructFieldType (HirId ref, HirId ty_ref, std::string name, TyBase *ty)
- : TyBase (ref, ty_ref, TypeKind::FIELD), name (name), ty (ty)
+ StructFieldType (HirId ref, HirId ty_ref, std::string name, TyBase *ty,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::FIELD, refs), name (name), ty (ty)
{}
void accept_vis (TyVisitor &vis) override;
@@ -166,19 +202,61 @@ private:
TyBase *ty;
};
+class TupleType : public TyBase
+{
+public:
+ TupleType (HirId ref, std::vector<HirId> fields,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::TUPLE, refs), fields (fields)
+ {}
+
+ TupleType (HirId ref, HirId ty_ref, std::vector<HirId> fields,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::TUPLE, refs), fields (fields)
+ {}
+
+ void accept_vis (TyVisitor &vis) override;
+
+ bool is_unit () const override { return false; }
+
+ std::string as_string () const override;
+
+ TyBase *combine (TyBase *other) override;
+
+ size_t num_fields () const { return fields.size (); }
+
+ TyBase *get_field (size_t index) const;
+
+ TyBase *clone () final override;
+
+ void iterate_fields (std::function<bool (TyBase *)> cb) const
+ {
+ for (size_t i = 0; i < num_fields (); i++)
+ {
+ if (!cb (get_field (i)))
+ return;
+ }
+ }
+
+private:
+ std::vector<HirId> fields;
+};
+
class ADTType : public TyBase
{
public:
- ADTType (HirId ref, std::string identifier, bool is_tuple,
- std::vector<StructFieldType *> fields)
- : TyBase (ref, ref, TypeKind::ADT), identifier (identifier),
- is_tuple (is_tuple), fields (fields)
+ ADTType (HirId ref, std::string identifier,
+ std::vector<StructFieldType *> fields,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::ADT, refs), identifier (identifier),
+ fields (fields)
{}
- ADTType (HirId ref, HirId ty_ref, std::string identifier, bool is_tuple,
- std::vector<StructFieldType *> fields)
- : TyBase (ref, ty_ref, TypeKind::ADT), identifier (identifier),
- is_tuple (is_tuple), fields (fields)
+ ADTType (HirId ref, HirId ty_ref, std::string identifier,
+ std::vector<StructFieldType *> fields,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::ADT, refs), identifier (identifier),
+ fields (fields)
{}
void accept_vis (TyVisitor &vis) override;
@@ -193,8 +271,6 @@ public:
std::string get_name () const { return identifier; }
- bool is_tuple_struct () const { return is_tuple; }
-
StructFieldType *get_field (size_t index) { return fields.at (index); }
StructFieldType *get_field (const std::string &lookup,
@@ -230,7 +306,6 @@ public:
private:
std::string identifier;
- bool is_tuple;
std::vector<StructFieldType *> fields;
};
@@ -238,15 +313,15 @@ class FnType : public TyBase
{
public:
FnType (HirId ref, std::vector<std::pair<HIR::Pattern *, TyBase *> > params,
- TyBase *type)
- : TyBase (ref, ref, TypeKind::FNDEF), params (std::move (params)),
+ TyBase *type, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::FNDEF, refs), params (std::move (params)),
type (type)
{}
FnType (HirId ref, HirId ty_ref,
std::vector<std::pair<HIR::Pattern *, TyBase *> > params,
- TyBase *type)
- : TyBase (ref, ty_ref, TypeKind::FNDEF), params (params), type (type)
+ TyBase *type, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::FNDEF, refs), params (params), type (type)
{}
void accept_vis (TyVisitor &vis) override;
@@ -281,12 +356,16 @@ private:
class ArrayType : public TyBase
{
public:
- ArrayType (HirId ref, size_t capacity, TyBase *type)
- : TyBase (ref, ref, TypeKind::ARRAY), capacity (capacity), type (type)
+ ArrayType (HirId ref, size_t capacity, TyBase *type,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::ARRAY, refs), capacity (capacity),
+ element_type_id (type->get_ref ())
{}
- ArrayType (HirId ref, HirId ty_ref, size_t capacity, TyBase *type)
- : TyBase (ref, ty_ref, TypeKind::ARRAY), capacity (capacity), type (type)
+ ArrayType (HirId ref, HirId ty_ref, size_t capacity, TyBase *type,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::ARRAY, refs), capacity (capacity),
+ element_type_id (type->get_ref ())
{}
void accept_vis (TyVisitor &vis) override;
@@ -297,21 +376,27 @@ public:
size_t get_capacity () const { return capacity; }
- TyBase *get_type () { return type; }
+ HirId element_type_ref () const { return element_type_id; }
+
+ TyBase *get_type () const;
TyBase *clone () final override;
private:
size_t capacity;
- TyBase *type;
+ HirId element_type_id;
};
class BoolType : public TyBase
{
public:
- BoolType (HirId ref) : TyBase (ref, ref, TypeKind::BOOL) {}
+ BoolType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::BOOL, refs)
+ {}
- BoolType (HirId ref, HirId ty_ref) : TyBase (ref, ty_ref, TypeKind::BOOL) {}
+ BoolType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::BOOL, refs)
+ {}
void accept_vis (TyVisitor &vis) override;
@@ -334,12 +419,13 @@ public:
I128
};
- IntType (HirId ref, IntKind kind)
- : TyBase (ref, ref, TypeKind::INT), int_kind (kind)
+ IntType (HirId ref, IntKind kind, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::INT, refs), int_kind (kind)
{}
- IntType (HirId ref, HirId ty_ref, IntKind kind)
- : TyBase (ref, ty_ref, TypeKind::INT), int_kind (kind)
+ IntType (HirId ref, HirId ty_ref, IntKind kind,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::INT, refs), int_kind (kind)
{}
void accept_vis (TyVisitor &vis) override;
@@ -368,12 +454,13 @@ public:
U128
};
- UintType (HirId ref, UintKind kind)
- : TyBase (ref, ref, TypeKind::UINT), uint_kind (kind)
+ UintType (HirId ref, UintKind kind, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::UINT, refs), uint_kind (kind)
{}
- UintType (HirId ref, HirId ty_ref, UintKind kind)
- : TyBase (ref, ty_ref, TypeKind::UINT), uint_kind (kind)
+ UintType (HirId ref, HirId ty_ref, UintKind kind,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::UINT, refs), uint_kind (kind)
{}
void accept_vis (TyVisitor &vis) override;
@@ -399,12 +486,14 @@ public:
F64
};
- FloatType (HirId ref, FloatKind kind)
- : TyBase (ref, ref, TypeKind::FLOAT), float_kind (kind)
+ FloatType (HirId ref, FloatKind kind,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::FLOAT, refs), float_kind (kind)
{}
- FloatType (HirId ref, HirId ty_ref, FloatKind kind)
- : TyBase (ref, ty_ref, TypeKind::FLOAT), float_kind (kind)
+ FloatType (HirId ref, HirId ty_ref, FloatKind kind,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::FLOAT, refs), float_kind (kind)
{}
void accept_vis (TyVisitor &vis) override;
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index 951bdcc..925130f 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -159,6 +159,7 @@ Mappings::get_next_hir_id (CrateNum crateNum)
auto id = it->second + 1;
hirIdIter[crateNum] = id;
+ hirNodesWithinCrate[crateNum].insert (id);
return id;
}
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index 3818be9..4859d1e 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -143,6 +143,11 @@ public:
return resolve_nodeid_to_stmt (get_current_crate (), id, stmt);
}
+ std::set<HirId> &get_hirids_within_crate (CrateNum crate)
+ {
+ return hirNodesWithinCrate[crate];
+ }
+
private:
Mappings ();
@@ -171,6 +176,9 @@ private:
// reverse mappings
std::map<CrateNum, std::map<NodeId, HirId> > nodeIdToHirMappings;
+
+ // all hirid nodes
+ std::map<CrateNum, std::set<HirId> > hirNodesWithinCrate;
};
} // namespace Analysis
diff --git a/gcc/testsuite/rust.test/compilable/ints_infer1.rs b/gcc/testsuite/rust.test/compilable/ints_infer1.rs
new file mode 100644
index 0000000..3170c7c
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/ints_infer1.rs
@@ -0,0 +1,18 @@
+const TEST_CONST: i32 = 10;
+
+fn main() {
+ let mut x = TEST_CONST;
+ x = x + 1;
+
+ let mut y = x + TEST_CONST;
+
+ let z = 1u32;
+
+ let a = z;
+
+ let b;
+ b = 1;
+
+ let c;
+ c = a;
+}
diff --git a/gcc/testsuite/rust.test/compilable/type_infer6.rs b/gcc/testsuite/rust.test/compilable/type_infer6.rs
new file mode 100644
index 0000000..f6eac9e
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/type_infer6.rs
@@ -0,0 +1,12 @@
+fn test(x: u32) -> u32 {
+ return x + 1;
+}
+
+fn main() {
+ let a;
+ a = 1;
+ let b = test(a);
+
+ let c = 1;
+ let d = test(c + 1);
+}