aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-07-26 14:08:28 +0000
committerGitHub <noreply@github.com>2021-07-26 14:08:28 +0000
commitf4dd2434cf3db67f86accd41f7c0c511a33425c7 (patch)
tree44fd8555d42abd6b04b3cd9f653c28d6a25d9e44
parenta4e3ffd3768b4a985aa7a137c9a553a4588acaba (diff)
parent5313e4fbe7cd5cead248e6b61c558d9edbe91236 (diff)
downloadgcc-f4dd2434cf3db67f86accd41f7c0c511a33425c7.zip
gcc-f4dd2434cf3db67f86accd41f7c0c511a33425c7.tar.gz
gcc-f4dd2434cf3db67f86accd41f7c0c511a33425c7.tar.bz2
Merge #592
592: TypeCastExpr r=philberty a=philberty This is the initial type casting rules more test cases will be added over time. To find gaps. Fixes #158 Co-authored-by: Philip Herron <philip.herron@embecosm.com> Co-authored-by: Mark Wielaard <mark@klomp.org>
-rw-r--r--gcc/rust/backend/rust-compile-expr.h18
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.h2
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h19
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc9
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h20
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h6
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h10
-rw-r--r--gcc/rust/typecheck/rust-tyty-cast.h1256
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc140
-rw-r--r--gcc/rust/typecheck/rust-tyty.h23
-rw-r--r--gcc/testsuite/rust/compile/cast1.rs5
-rw-r--r--gcc/testsuite/rust/compile/torture/cast1.rs5
-rw-r--r--gcc/testsuite/rust/compile/torture/cast2.rs5
-rw-r--r--gcc/testsuite/rust/compile/torture/cast3.rs6
14 files changed, 1520 insertions, 4 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index fa6a539..2a147ab 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -417,6 +417,24 @@ public:
= ctx->get_backend ()->negation_expression (op, negated_expr, location);
}
+ void visit (HIR::TypeCastExpr &expr) override
+ {
+ TyTy::BaseType *tyty_to_cast_to = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
+ &tyty_to_cast_to))
+ {
+ translated = ctx->get_backend ()->error_expression ();
+ return;
+ }
+
+ auto type_to_cast_to = TyTyResolveCompile::compile (ctx, tyty_to_cast_to);
+ auto casted_expr
+ = CompileExpr::Compile (expr.get_casted_expr ().get (), ctx);
+ translated
+ = ctx->get_backend ()->convert_expression (type_to_cast_to, casted_expr,
+ expr.get_locus ());
+ }
+
void visit (HIR::IfExpr &expr) override
{
auto stmt = CompileConditionalBlocks::compile (&expr, ctx, nullptr);
diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
index a3baf50..742cb1d 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -295,6 +295,8 @@ protected:
HIR::GenericArgsBinding lower_binding (AST::GenericArgsBinding &binding);
HIR::SelfParam lower_self (AST::SelfParam &self);
+
+ HIR::Type *lower_type_no_bounds (AST::TypeNoBounds *type);
};
} // namespace HIR
diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h
index 7bc3ab4..1c48651 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.h
+++ b/gcc/rust/hir/rust-ast-lower-expr.h
@@ -410,6 +410,25 @@ public:
expr.get_locus ());
}
+ void visit (AST::TypeCastExpr &expr) override
+ {
+ HIR::Expr *expr_to_cast_to
+ = ASTLoweringExpr::translate (expr.get_casted_expr ().get ());
+ HIR::Type *type_to_cast_to
+ = lower_type_no_bounds (expr.get_type_to_cast_to ().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::TypeCastExpr (mapping,
+ std::unique_ptr<HIR::Expr> (expr_to_cast_to),
+ std::unique_ptr<HIR::Type> (type_to_cast_to),
+ expr.get_locus ());
+ }
+
/* Compound assignment expression is compiled away. */
void visit (AST::CompoundAssignmentExpr &expr) override
{
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index 516b5ba..04587ed 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -21,6 +21,7 @@
#include "rust-ast-lower-implitem.h"
#include "rust-ast-lower-expr.h"
#include "rust-ast-lower-block.h"
+#include "rust-ast-lower-type.h"
namespace Rust {
namespace HIR {
@@ -394,5 +395,13 @@ ASTLowerTypePath::visit (AST::TypePathSegmentGeneric &segment)
segment.get_locus ());
}
+// rust-ast-lower-base
+
+HIR::Type *
+ASTLoweringBase::lower_type_no_bounds (AST::TypeNoBounds *type)
+{
+ return ASTLoweringType::translate (type);
+}
+
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index 1d5b6e6..65c40d6 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -538,7 +538,7 @@ protected:
// Binary infix "as" chir expression.
class TypeCastExpr : public OperatorExpr
{
- std::unique_ptr<TypeNoBounds> type_to_convert_to;
+ std::unique_ptr<Type> type_to_convert_to;
// Note: only certain type casts allowed, outlined in reference
public:
@@ -547,7 +547,7 @@ public:
// Constructor requires calling protected constructor of OperatorExpr
TypeCastExpr (Analysis::NodeMapping mappings,
std::unique_ptr<Expr> expr_to_cast,
- std::unique_ptr<TypeNoBounds> type_to_cast_to, Location locus)
+ std::unique_ptr<Type> type_to_cast_to, Location locus)
: OperatorExpr (std::move (mappings), std::move (expr_to_cast),
AST::AttrVec (), locus),
type_to_convert_to (std::move (type_to_cast_to))
@@ -557,7 +557,7 @@ public:
// Copy constructor also requires calling protected constructor
TypeCastExpr (TypeCastExpr const &other)
: OperatorExpr (other),
- type_to_convert_to (other.type_to_convert_to->clone_type_no_bounds ())
+ type_to_convert_to (other.type_to_convert_to->clone_type ())
{}
// Overload assignment operator to deep copy
@@ -565,7 +565,7 @@ public:
{
OperatorExpr::operator= (other);
// main_or_left_expr = other.main_or_left_expr->clone_expr();
- type_to_convert_to = other.type_to_convert_to->clone_type_no_bounds ();
+ type_to_convert_to = other.type_to_convert_to->clone_type ();
return *this;
}
@@ -576,6 +576,18 @@ public:
void accept_vis (HIRVisitor &vis) override;
+ std::unique_ptr<Expr> &get_casted_expr ()
+ {
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
+ }
+
+ std::unique_ptr<Type> &get_type_to_convert_to ()
+ {
+ rust_assert (type_to_convert_to != nullptr);
+ return type_to_convert_to;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h
index 7abf10a..e7e37d4 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.h
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.h
@@ -174,6 +174,12 @@ public:
ResolveExpr::go (expr.get_negated_expr ().get (), expr.get_node_id ());
}
+ void visit (AST::TypeCastExpr &expr) override
+ {
+ ResolveType::go (expr.get_type_to_cast_to ().get (), expr.get_node_id ());
+ ResolveExpr::go (expr.get_casted_expr ().get (), expr.get_node_id ());
+ }
+
void visit (AST::IfExpr &expr) override
{
ResolveExpr::go (expr.get_condition_expr ().get (), expr.get_node_id ());
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 6e5b231..bd42b4c 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -1147,6 +1147,16 @@ public:
}
}
+ void visit (HIR::TypeCastExpr &expr) override
+ {
+ TyTy::BaseType *expr_to_convert
+ = TypeCheckExpr::Resolve (expr.get_casted_expr ().get (), false);
+ TyTy::BaseType *tyty_to_convert_to
+ = TypeCheckType::Resolve (expr.get_type_to_convert_to ().get ());
+
+ infered = expr_to_convert->cast (tyty_to_convert_to);
+ }
+
private:
TypeCheckExpr (bool inside_loop)
: TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr),
diff --git a/gcc/rust/typecheck/rust-tyty-cast.h b/gcc/rust/typecheck/rust-tyty-cast.h
new file mode 100644
index 0000000..de59b32
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-cast.h
@@ -0,0 +1,1256 @@
+// 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_CAST_RULES
+#define RUST_TYTY_CAST_RULES
+
+#include "rust-diagnostics.h"
+#include "rust-tyty.h"
+#include "rust-tyty-visitor.h"
+#include "rust-hir-map.h"
+#include "rust-hir-type-check.h"
+
+extern ::Backend *
+rust_get_backend ();
+
+namespace Rust {
+namespace TyTy {
+
+class BaseCastRules : public TyVisitor
+{
+public:
+ virtual ~BaseCastRules () {}
+
+ virtual BaseType *cast (BaseType *other)
+ {
+ if (other->get_kind () == TypeKind::PARAM)
+ {
+ ParamType *p = static_cast<ParamType *> (other);
+ if (p->can_resolve ())
+ {
+ other = p->resolve ();
+ }
+ }
+
+ other->accept_vis (*this);
+ if (resolved->get_kind () == TyTy::TypeKind::ERROR)
+ return resolved;
+
+ resolved->append_reference (get_base ()->get_ref ());
+ resolved->append_reference (other->get_ref ());
+ for (auto ref : get_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;
+ bool result_is_infer_var = resolved->get_kind () == TyTy::TypeKind::INFER;
+ bool results_is_non_general_infer_var
+ = (result_is_infer_var
+ && (static_cast<InferType *> (resolved))->get_infer_kind ()
+ != TyTy::InferType::GENERAL);
+ if (result_resolved || results_is_non_general_infer_var)
+ {
+ for (auto &ref : resolved->get_combined_refs ())
+ {
+ TyTy::BaseType *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)
+ {
+ context->insert_type (
+ Analysis::NodeMapping (mappings->get_current_crate (),
+ UNKNOWN_NODEID, ref,
+ UNKNOWN_LOCAL_DEFID),
+ resolved->clone ());
+ }
+ }
+ }
+ return resolved;
+ }
+
+ virtual void visit (TupleType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_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 base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (InferType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (FnType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (FnPtr &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (ArrayType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (BoolType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (IntType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (UintType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (USizeType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (ISizeType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (FloatType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (ErrorType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (CharType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (ReferenceType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (PointerType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (ParamType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (StrType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (NeverType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+ virtual void visit (PlaceholderType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
+protected:
+ BaseCastRules (BaseType *base)
+ : mappings (Analysis::Mappings::get ()),
+ context (Resolver::TypeCheckContext::get ()),
+ resolved (new ErrorType (base->get_ref (), base->get_ref ()))
+ {}
+
+ Analysis::Mappings *mappings;
+ Resolver::TypeCheckContext *context;
+
+ /* Temporary storage for the result of a unification.
+ We could return the result directly instead of storing it in the rule
+ object, but that involves modifying the visitor pattern to accommodate
+ the return value, which is too complex. */
+ BaseType *resolved;
+
+private:
+ /* Returns a pointer to the ty that created this rule. */
+ virtual BaseType *get_base () = 0;
+};
+
+class InferCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ InferCastRules (InferType *base) : BaseCastRules (base), base (base) {}
+
+ void visit (BoolType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseCastRules::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;
+ }
+
+ BaseCastRules::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;
+ }
+
+ BaseCastRules::visit (type);
+ }
+
+ void visit (USizeType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
+ || (base->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::INTEGRAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseCastRules::visit (type);
+ }
+
+ void visit (ISizeType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
+ || (base->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::INTEGRAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseCastRules::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;
+ }
+
+ BaseCastRules::visit (type);
+ }
+
+ void visit (ArrayType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseCastRules::visit (type);
+ }
+
+ void visit (ADTType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseCastRules::visit (type);
+ }
+
+ void visit (TupleType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseCastRules::visit (type);
+ }
+
+ void visit (InferType &type) override
+ {
+ switch (base->get_infer_kind ())
+ {
+ case InferType::InferTypeKind::GENERAL:
+ resolved = type.clone ();
+ return;
+
+ 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;
+ }
+
+ BaseCastRules::visit (type);
+ }
+
+ void visit (CharType &type) override
+ {
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseCastRules::visit (type);
+ }
+ }
+
+ void visit (ReferenceType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseCastRules::visit (type);
+ }
+
+ void visit (PointerType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseCastRules::visit (type);
+ }
+
+ void visit (ParamType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseCastRules::visit (type);
+ }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ InferType *base;
+};
+
+class FnCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ FnCastRules (FnType *base) : BaseCastRules (base), base (base) {}
+
+ void visit (InferType &type) override
+ {
+ if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
+ }
+
+ void visit (FnType &type) override
+ {
+ if (base->num_params () != type.num_params ())
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ for (size_t i = 0; i < base->num_params (); i++)
+ {
+ auto a = base->param_at (i).second;
+ auto b = type.param_at (i).second;
+
+ auto unified_param = a->unify (b);
+ if (unified_param == nullptr)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+ }
+
+ auto unified_return
+ = base->get_return_type ()->unify (type.get_return_type ());
+ if (unified_return == nullptr)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
+ }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ FnType *base;
+};
+
+class FnptrCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ FnptrCastRules (FnPtr *base) : BaseCastRules (base), base (base) {}
+
+ void visit (InferType &type) override
+ {
+ if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
+ }
+
+ void visit (FnPtr &type) override
+ {
+ auto this_ret_type = base->get_return_type ();
+ auto other_ret_type = type.get_return_type ();
+ auto unified_result = this_ret_type->unify (other_ret_type);
+ if (unified_result == nullptr
+ || unified_result->get_kind () == TypeKind::ERROR)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ if (base->num_params () != type.num_params ())
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ for (size_t i = 0; i < base->num_params (); i++)
+ {
+ auto this_param = base->param_at (i);
+ auto other_param = type.param_at (i);
+ auto unified_param = this_param->unify (other_param);
+ if (unified_param == nullptr
+ || unified_param->get_kind () == TypeKind::ERROR)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
+ }
+
+ void visit (FnType &type) override
+ {
+ auto this_ret_type = base->get_return_type ();
+ auto other_ret_type = type.get_return_type ();
+ auto unified_result = this_ret_type->unify (other_ret_type);
+ if (unified_result == nullptr
+ || unified_result->get_kind () == TypeKind::ERROR)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ if (base->num_params () != type.num_params ())
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ for (size_t i = 0; i < base->num_params (); i++)
+ {
+ auto this_param = base->param_at (i);
+ auto other_param = type.param_at (i).second;
+ auto unified_param = this_param->unify (other_param);
+ if (unified_param == nullptr
+ || unified_param->get_kind () == TypeKind::ERROR)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
+ }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ FnPtr *base;
+};
+
+class ArrayCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ ArrayCastRules (ArrayType *base) : BaseCastRules (base), base (base) {}
+
+ void visit (ArrayType &type) override
+ {
+ // check base type
+ auto base_resolved
+ = base->get_element_type ()->unify (type.get_element_type ());
+ if (base_resolved == nullptr)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ auto backend = rust_get_backend ();
+
+ // need to check the base types and capacity
+ if (!backend->const_values_equal (type.get_capacity (),
+ base->get_capacity ()))
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ resolved
+ = new ArrayType (type.get_ref (), type.get_ty_ref (),
+ type.get_capacity (), TyVar (base_resolved->get_ref ()));
+ }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ ArrayType *base;
+};
+
+class BoolCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ BoolCastRules (BoolType *base) : BaseCastRules (base), base (base) {}
+
+ void visit (BoolType &type) override
+ {
+ resolved = new BoolType (type.get_ref (), type.get_ty_ref ());
+ }
+
+ void visit (InferType &type) override
+ {
+ switch (type.get_infer_kind ())
+ {
+ case InferType::InferTypeKind::GENERAL:
+ resolved = base->clone ();
+ break;
+
+ default:
+ BaseCastRules::visit (type);
+ break;
+ }
+ }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ BoolType *base;
+};
+
+class IntCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ IntCastRules (IntType *base) : BaseCastRules (base), base (base) {}
+
+ void visit (InferType &type) override
+ {
+ // cant assign a float inference variable
+ if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
+ }
+
+ 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 (USizeType &type) override { resolved = type.clone (); }
+
+ void visit (ISizeType &type) override { resolved = type.clone (); }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ IntType *base;
+};
+
+class UintCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ UintCastRules (UintType *base) : BaseCastRules (base), base (base) {}
+
+ void visit (InferType &type) override
+ {
+ // cant assign a float inference variable
+ if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
+ }
+
+ 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 (USizeType &type) override { resolved = type.clone (); }
+
+ void visit (ISizeType &type) override { resolved = type.clone (); }
+
+ void visit (CharType &type) override
+ {
+ // error[E0604]: only `u8` can be cast as `char`, not `i32`
+ if (base->get_uint_kind () != UintType::UintKind::U8)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ resolved = type.clone ();
+ }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ UintType *base;
+};
+
+class FloatCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ FloatCastRules (FloatType *base) : BaseCastRules (base), base (base) {}
+
+ void visit (InferType &type) override
+ {
+ if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
+ }
+
+ 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 (USizeType &type) override { resolved = type.clone (); }
+
+ void visit (ISizeType &type) override { resolved = type.clone (); }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ FloatType *base;
+};
+
+class ADTCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ ADTCastRules (ADTType *base) : BaseCastRules (base), base (base) {}
+
+ void visit (ADTType &type) override
+ {
+ if (base->get_identifier ().compare (type.get_identifier ()) != 0)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ if (base->num_fields () != type.num_fields ())
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ for (size_t i = 0; i < type.num_fields (); ++i)
+ {
+ TyTy::StructFieldType *base_field = base->get_field (i);
+ TyTy::StructFieldType *other_field = type.get_field (i);
+
+ TyTy::BaseType *this_field_ty = base_field->get_field_type ();
+ TyTy::BaseType *other_field_ty = other_field->get_field_type ();
+
+ BaseType *unified_ty = this_field_ty->unify (other_field_ty);
+ if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+ }
+
+ resolved = type.clone ();
+ }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ ADTType *base;
+};
+
+class TupleCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ TupleCastRules (TupleType *base) : BaseCastRules (base), base (base) {}
+
+ void visit (TupleType &type) override
+ {
+ if (base->num_fields () != type.num_fields ())
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ std::vector<TyVar> fields;
+ for (size_t i = 0; i < base->num_fields (); i++)
+ {
+ BaseType *bo = base->get_field (i);
+ BaseType *fo = type.get_field (i);
+
+ BaseType *unified_ty = bo->unify (fo);
+ if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+
+ fields.push_back (TyVar (unified_ty->get_ref ()));
+ }
+
+ resolved
+ = new TyTy::TupleType (type.get_ref (), type.get_ty_ref (), fields);
+ }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ TupleType *base;
+};
+
+class USizeCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ USizeCastRules (USizeType *base) : BaseCastRules (base), base (base) {}
+
+ void visit (InferType &type) override
+ {
+ // cant assign a float inference variable
+ if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
+ }
+
+ 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 (USizeType &type) override { resolved = type.clone (); }
+
+ void visit (ISizeType &type) override { resolved = type.clone (); }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ USizeType *base;
+};
+
+class ISizeCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ ISizeCastRules (ISizeType *base) : BaseCastRules (base), base (base) {}
+
+ void visit (InferType &type) override
+ {
+ // cant assign a float inference variable
+ if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
+ }
+
+ 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 (USizeType &type) override { resolved = type.clone (); }
+
+ void visit (ISizeType &type) override { resolved = type.clone (); }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ ISizeType *base;
+};
+
+class CharCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ CharCastRules (CharType *base) : BaseCastRules (base), base (base) {}
+
+ void visit (InferType &type) override
+ {
+ if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
+ }
+
+ void visit (CharType &type) override { resolved = type.clone (); }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ CharType *base;
+};
+
+class ReferenceCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ ReferenceCastRules (ReferenceType *base) : BaseCastRules (base), base (base)
+ {}
+
+ void visit (ReferenceType &type) override { resolved = type.clone (); }
+
+ void visit (PointerType &type) override
+ {
+ auto base_type = base->get_base ();
+ auto other_base_type = type.get_base ();
+
+ TyTy::BaseType *base_resolved = base_type->unify (other_base_type);
+ if (base_resolved == nullptr
+ || base_resolved->get_kind () == TypeKind::ERROR)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ resolved = type.clone ();
+ }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ ReferenceType *base;
+};
+
+class PointerCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ PointerCastRules (PointerType *base) : BaseCastRules (base), base (base) {}
+
+ void visit (ReferenceType &type) override
+ {
+ auto base_type = base->get_base ();
+ auto other_base_type = type.get_base ();
+
+ TyTy::BaseType *base_resolved = base_type->unify (other_base_type);
+ if (base_resolved == nullptr
+ || base_resolved->get_kind () == TypeKind::ERROR)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ resolved = type.clone ();
+ }
+
+ void visit (PointerType &type) override { resolved = type.clone (); }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ PointerType *base;
+};
+
+class ParamCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ ParamCastRules (ParamType *base) : BaseCastRules (base), base (base) {}
+
+ // param types are a placeholder we shouldn't have cases where we unify
+ // against it. eg: struct foo<T> { a: T }; When we invoke it we can do either:
+ //
+ // foo<i32>{ a: 123 }.
+ // Then this enforces the i32 type to be referenced on the
+ // field via an hirid.
+ //
+ // rust also allows for a = foo{a:123}; Where we can use an Inference Variable
+ // to handle the typing of the struct
+ BaseType *cast (BaseType *other) override final
+ {
+ if (base->get_ref () == base->get_ty_ref ())
+ return BaseCastRules::cast (other);
+
+ auto context = Resolver::TypeCheckContext::get ();
+ BaseType *lookup = nullptr;
+ bool ok = context->lookup_type (base->get_ty_ref (), &lookup);
+ rust_assert (ok);
+
+ return lookup->unify (other);
+ }
+
+ void visit (ParamType &type) override
+ {
+ if (base->get_symbol ().compare (type.get_symbol ()) != 0)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ resolved = type.clone ();
+ }
+
+ void visit (InferType &type) override
+ {
+ if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
+ {
+ BaseCastRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ ParamType *base;
+};
+
+class StrCastRules : public BaseCastRules
+{
+ // FIXME we will need a enum for the StrType like ByteBuf etc..
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ StrCastRules (StrType *base) : BaseCastRules (base), base (base) {}
+
+ void visit (StrType &type) override { resolved = type.clone (); }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ StrType *base;
+};
+
+class NeverCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ NeverCastRules (NeverType *base) : BaseCastRules (base), base (base) {}
+
+ virtual void visit (NeverType &type) override { resolved = type.clone (); }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ NeverType *base;
+};
+
+class PlaceholderCastRules : public BaseCastRules
+{
+ using Rust::TyTy::BaseCastRules::visit;
+
+public:
+ PlaceholderCastRules (PlaceholderType *base)
+ : BaseCastRules (base), base (base)
+ {}
+
+private:
+ BaseType *get_base () override { return base; }
+
+ PlaceholderType *base;
+};
+
+} // namespace TyTy
+} // namespace Rust
+
+#endif // RUST_TYTY_CAST_RULES
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index f043c7e..bb5d6c0 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -24,6 +24,7 @@
#include "rust-tyty-rules.h"
#include "rust-tyty-cmp.h"
#include "rust-tyty-coercion.h"
+#include "rust-tyty-cast.h"
#include "rust-hir-map.h"
#include "rust-substitution-mapper.h"
@@ -119,6 +120,13 @@ InferType::coerce (BaseType *other)
}
BaseType *
+InferType::cast (BaseType *other)
+{
+ InferCastRules r (this);
+ return r.cast (other);
+}
+
+BaseType *
InferType::clone ()
{
return new InferType (get_ref (), get_ty_ref (), get_infer_kind (),
@@ -187,6 +195,12 @@ ErrorType::coerce (BaseType *other)
}
BaseType *
+ErrorType::cast (BaseType *other)
+{
+ return this;
+}
+
+BaseType *
ErrorType::clone ()
{
return new ErrorType (get_ref (), get_ty_ref (), get_combined_refs ());
@@ -459,6 +473,13 @@ ADTType::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+ADTType::cast (BaseType *other)
+{
+ ADTCastRules r (this);
+ return r.cast (other);
+}
+
bool
ADTType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -633,6 +654,13 @@ TupleType::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+TupleType::cast (BaseType *other)
+{
+ TupleCastRules r (this);
+ return r.cast (other);
+}
+
bool
TupleType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -730,6 +758,13 @@ FnType::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+FnType::cast (BaseType *other)
+{
+ FnCastRules r (this);
+ return r.cast (other);
+}
+
bool
FnType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -938,6 +973,13 @@ FnPtr::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+FnPtr::cast (BaseType *other)
+{
+ FnptrCastRules r (this);
+ return r.cast (other);
+}
+
bool
FnPtr::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1018,6 +1060,13 @@ ArrayType::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+ArrayType::cast (BaseType *other)
+{
+ ArrayCastRules r (this);
+ return r.cast (other);
+}
+
bool
ArrayType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1086,6 +1135,13 @@ BoolType::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+BoolType::cast (BaseType *other)
+{
+ BoolCastRules r (this);
+ return r.cast (other);
+}
+
bool
BoolType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1145,6 +1201,13 @@ IntType::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+IntType::cast (BaseType *other)
+{
+ IntCastRules r (this);
+ return r.cast (other);
+}
+
bool
IntType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1215,6 +1278,13 @@ UintType::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+UintType::cast (BaseType *other)
+{
+ UintCastRules r (this);
+ return r.cast (other);
+}
+
bool
UintType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1279,6 +1349,13 @@ FloatType::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+FloatType::cast (BaseType *other)
+{
+ FloatCastRules r (this);
+ return r.cast (other);
+}
+
bool
FloatType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1335,6 +1412,13 @@ USizeType::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+USizeType::cast (BaseType *other)
+{
+ USizeCastRules r (this);
+ return r.cast (other);
+}
+
bool
USizeType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1380,6 +1464,13 @@ ISizeType::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+ISizeType::cast (BaseType *other)
+{
+ ISizeCastRules r (this);
+ return r.cast (other);
+}
+
bool
ISizeType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1425,6 +1516,13 @@ CharType::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+CharType::cast (BaseType *other)
+{
+ CharCastRules r (this);
+ return r.cast (other);
+}
+
bool
CharType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1471,6 +1569,13 @@ ReferenceType::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+ReferenceType::cast (BaseType *other)
+{
+ ReferenceCastRules r (this);
+ return r.cast (other);
+}
+
bool
ReferenceType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1550,6 +1655,13 @@ PointerType::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+PointerType::cast (BaseType *other)
+{
+ PointerCastRules r (this);
+ return r.cast (other);
+}
+
bool
PointerType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1638,6 +1750,13 @@ ParamType::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+ParamType::cast (BaseType *other)
+{
+ ParamCastRules r (this);
+ return r.cast (other);
+}
+
bool
ParamType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1751,6 +1870,13 @@ StrType::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+StrType::cast (BaseType *other)
+{
+ StrCastRules r (this);
+ return r.cast (other);
+}
+
bool
StrType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1796,6 +1922,13 @@ NeverType::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+NeverType::cast (BaseType *other)
+{
+ NeverCastRules r (this);
+ return r.cast (other);
+}
+
bool
NeverType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1841,6 +1974,13 @@ PlaceholderType::coerce (BaseType *other)
return r.coerce (other);
}
+BaseType *
+PlaceholderType::cast (BaseType *other)
+{
+ PlaceholderCastRules r (this);
+ return r.cast (other);
+}
+
bool
PlaceholderType::can_eq (const BaseType *other, bool emit_errors) const
{
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 2152c1b..cecf69a 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -174,6 +174,9 @@ public:
// this is the base coercion interface for types
virtual BaseType *coerce (BaseType *other) = 0;
+ // this is the cast interface for TypeCastExpr
+ virtual BaseType *cast (BaseType *other) = 0;
+
// Check value equality between two ty. Type inference rules are ignored. Two
// ty are considered equal if they're of the same kind, and
// 1. (For ADTs, arrays, tuples, refs) have the same underlying ty
@@ -295,6 +298,7 @@ public:
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
BaseType *clone () final override;
@@ -331,6 +335,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
BaseType *clone () final override;
@@ -361,6 +366,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
BaseType *clone () final override;
@@ -448,6 +454,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
bool is_equal (const BaseType &other) const override;
@@ -882,6 +889,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
bool is_equal (const BaseType &other) const override;
@@ -1003,6 +1011,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
bool is_equal (const BaseType &other) const override;
@@ -1104,6 +1113,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
bool is_equal (const BaseType &other) const override;
@@ -1148,6 +1158,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
bool is_equal (const BaseType &other) const override;
@@ -1189,6 +1200,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
BaseType *clone () final override;
};
@@ -1224,6 +1236,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
IntKind get_int_kind () const { return int_kind; }
@@ -1266,6 +1279,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
UintKind get_uint_kind () const { return uint_kind; }
@@ -1306,6 +1320,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
FloatKind get_float_kind () const { return float_kind; }
@@ -1338,6 +1353,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
BaseType *clone () final override;
};
@@ -1363,6 +1379,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
BaseType *clone () final override;
};
@@ -1388,6 +1405,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
BaseType *clone () final override;
};
@@ -1417,6 +1435,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
bool is_equal (const BaseType &other) const override;
@@ -1462,6 +1481,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
bool is_equal (const BaseType &other) const override;
@@ -1504,6 +1524,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
bool is_equal (const BaseType &other) const override;
@@ -1539,6 +1560,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
BaseType *clone () final override;
@@ -1569,6 +1591,7 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
BaseType *clone () final override;
diff --git a/gcc/testsuite/rust/compile/cast1.rs b/gcc/testsuite/rust/compile/cast1.rs
new file mode 100644
index 0000000..74c4b1e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/cast1.rs
@@ -0,0 +1,5 @@
+fn main() {
+ let a: i32 = 123;
+ let b = a as char;
+ // { dg-error "invalid cast .i32. to .char." "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/cast1.rs b/gcc/testsuite/rust/compile/torture/cast1.rs
new file mode 100644
index 0000000..845d08c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/cast1.rs
@@ -0,0 +1,5 @@
+fn main() {
+ let a: *const i32 = &123;
+ let b: *mut i32 = (a as *mut i32);
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/cast2.rs b/gcc/testsuite/rust/compile/torture/cast2.rs
new file mode 100644
index 0000000..82925e9
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/cast2.rs
@@ -0,0 +1,5 @@
+fn main() {
+ let a: i32 = 123i32;
+ let b: u8 = a as u8;
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/torture/cast3.rs b/gcc/testsuite/rust/compile/torture/cast3.rs
new file mode 100644
index 0000000..1de9568
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/cast3.rs
@@ -0,0 +1,6 @@
+fn main() {
+ let a = "foo\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}