diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-07-26 14:08:28 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-26 14:08:28 +0000 |
commit | f4dd2434cf3db67f86accd41f7c0c511a33425c7 (patch) | |
tree | 44fd8555d42abd6b04b3cd9f653c28d6a25d9e44 | |
parent | a4e3ffd3768b4a985aa7a137c9a553a4588acaba (diff) | |
parent | 5313e4fbe7cd5cead248e6b61c558d9edbe91236 (diff) | |
download | gcc-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.h | 18 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-base.h | 2 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-expr.h | 19 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower.cc | 9 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-expr.h | 20 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-expr.h | 6 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 10 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty-cast.h | 1256 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 140 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.h | 23 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/cast1.rs | 5 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/torture/cast1.rs | 5 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/torture/cast2.rs | 5 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/torture/cast3.rs | 6 |
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 } +} |