diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-07-20 08:17:09 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-20 08:17:09 +0000 |
commit | 02713d245aaffd45d8daaf8c914b1dda5baa6eb4 (patch) | |
tree | c9119796d4330f6dda5d93f85de80044de723cb4 /gcc | |
parent | eea221e39ead0f45e9ef91aaf1b5ed855a4a5d8b (diff) | |
parent | f56781662f82dcbe1780cbe3e7eb4ac17f8156d0 (diff) | |
download | gcc-02713d245aaffd45d8daaf8c914b1dda5baa6eb4.zip gcc-02713d245aaffd45d8daaf8c914b1dda5baa6eb4.tar.gz gcc-02713d245aaffd45d8daaf8c914b1dda5baa6eb4.tar.bz2 |
Merge #577
577: Initial type coercion code r=philberty a=philberty
This is the initial type coercion code. Coercions are necessary to implement
mutability on reference types and for raw pointers in general.
Fixes #576 #352
Addresses #434
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/backend/rust-compile-context.h | 4 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 10 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-stmt.h | 2 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-type.h | 3 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty-coercion.h | 1198 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty-rules.h | 9 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 138 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.h | 130 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/reference1.rs | 5 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/torture/coercion1.rs | 11 |
10 files changed, 1428 insertions, 82 deletions
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index d822937..efca267 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -537,6 +537,10 @@ public: Btype *base_compiled_type = TyTyResolveCompile::compile (ctx, type.get_base ()); translated = ctx->get_backend ()->reference_type (base_compiled_type); + if (!type.is_mutable ()) + { + translated = ctx->get_backend ()->immutable_type (translated); + } } void visit (TyTy::StrType &type) override diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index dd10d42..b53cd46 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -348,7 +348,7 @@ public: auto lhs = TypeCheckExpr::Resolve (expr.get_lhs (), false); auto rhs = TypeCheckExpr::Resolve (expr.get_rhs (), false); - auto result = lhs->unify (rhs); + auto result = lhs->coerce (rhs); if (result->get_kind () == TyTy::TypeKind::ERROR) return; @@ -547,8 +547,9 @@ public: auto ok = context->lookup_builtin ("str", &base); rust_assert (ok); - infered = new TyTy::ReferenceType (expr.get_mappings ().get_hirid (), - TyTy::TyVar (base->get_ref ())); + infered + = new TyTy::ReferenceType (expr.get_mappings ().get_hirid (), + TyTy::TyVar (base->get_ref ()), false); } break; @@ -1088,7 +1089,8 @@ public: // FIXME double_reference infered = new TyTy::ReferenceType (expr.get_mappings ().get_hirid (), - TyTy::TyVar (resolved_base->get_ref ())); + TyTy::TyVar (resolved_base->get_ref ()), + expr.get_is_mut ()); } void visit (HIR::DereferenceExpr &expr) override diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index ba821ca..1b6f47c 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -80,7 +80,7 @@ public: // let x:i32 = 123; if (specified_ty != nullptr && init_expr_ty != nullptr) { - auto unified_ty = specified_ty->unify (init_expr_ty); + auto unified_ty = specified_ty->coerce (init_expr_ty); if (unified_ty->get_kind () == TyTy::TypeKind::ERROR) return; diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index e9a3bde..567d482 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -190,7 +190,8 @@ public: TyTy::BaseType *base = TypeCheckType::Resolve (type.get_base_type ().get ()); translated = new TyTy::ReferenceType (type.get_mappings ().get_hirid (), - TyTy::TyVar (base->get_ref ())); + TyTy::TyVar (base->get_ref ()), + type.get_has_mut ()); } void visit (HIR::InferredType &type) override diff --git a/gcc/rust/typecheck/rust-tyty-coercion.h b/gcc/rust/typecheck/rust-tyty-coercion.h new file mode 100644 index 0000000..5c10b04 --- /dev/null +++ b/gcc/rust/typecheck/rust-tyty-coercion.h @@ -0,0 +1,1198 @@ +// 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_COERCION_RULES +#define RUST_TYTY_COERCION_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 BaseCoercionRules : public TyVisitor +{ +public: + virtual ~BaseCoercionRules () {} + + virtual BaseType *coerce (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, "expected [%s] got [%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, "expected [%s] got [%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, "expected [%s] got [%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, "expected [%s] got [%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, "expected [%s] got [%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, "expected [%s] got [%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, "expected [%s] got [%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, "expected [%s] got [%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, "expected [%s] got [%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, "expected [%s] got [%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, "expected [%s] got [%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, "expected [%s] got [%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, "expected [%s] got [%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, "expected [%s] got [%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, "expected [%s] got [%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, "expected [%s] got [%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, "expected [%s] got [%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, "expected [%s] got [%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, "expected [%s] got [%s]", + get_base ()->as_string ().c_str (), + type.as_string ().c_str ()); + } + +protected: + BaseCoercionRules (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 InferCoercionRules : public BaseCoercionRules +{ + using Rust::TyTy::BaseCoercionRules::visit; + +public: + InferCoercionRules (InferType *base) : BaseCoercionRules (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; + } + + BaseCoercionRules::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; + } + + BaseCoercionRules::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; + } + + BaseCoercionRules::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; + } + + BaseCoercionRules::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; + } + + BaseCoercionRules::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; + } + + BaseCoercionRules::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; + } + + BaseCoercionRules::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; + } + + BaseCoercionRules::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; + } + + BaseCoercionRules::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; + } + + BaseCoercionRules::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; + } + + BaseCoercionRules::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; + } + + BaseCoercionRules::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; + } + + BaseCoercionRules::visit (type); + } + +private: + BaseType *get_base () override { return base; } + + InferType *base; +}; + +class FnCoercionRules : public BaseCoercionRules +{ + using Rust::TyTy::BaseCoercionRules::visit; + +public: + FnCoercionRules (FnType *base) : BaseCoercionRules (base), base (base) {} + + void visit (InferType &type) override + { + if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) + { + BaseCoercionRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); + } + + void visit (FnType &type) override + { + if (base->num_params () != type.num_params ()) + { + BaseCoercionRules::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) + { + BaseCoercionRules::visit (type); + return; + } + } + + auto unified_return + = base->get_return_type ()->unify (type.get_return_type ()); + if (unified_return == nullptr) + { + BaseCoercionRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); + } + +private: + BaseType *get_base () override { return base; } + + FnType *base; +}; + +class FnptrCoercionRules : public BaseCoercionRules +{ + using Rust::TyTy::BaseCoercionRules::visit; + +public: + FnptrCoercionRules (FnPtr *base) : BaseCoercionRules (base), base (base) {} + + void visit (InferType &type) override + { + if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) + { + BaseCoercionRules::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) + { + BaseCoercionRules::visit (type); + return; + } + + if (base->num_params () != type.num_params ()) + { + BaseCoercionRules::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) + { + BaseCoercionRules::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) + { + BaseCoercionRules::visit (type); + return; + } + + if (base->num_params () != type.num_params ()) + { + BaseCoercionRules::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) + { + BaseCoercionRules::visit (type); + return; + } + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); + } + +private: + BaseType *get_base () override { return base; } + + FnPtr *base; +}; + +class ArrayCoercionRules : public BaseCoercionRules +{ + using Rust::TyTy::BaseCoercionRules::visit; + +public: + ArrayCoercionRules (ArrayType *base) : BaseCoercionRules (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) + { + BaseCoercionRules::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 ())) + { + BaseCoercionRules::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 BoolCoercionRules : public BaseCoercionRules +{ + using Rust::TyTy::BaseCoercionRules::visit; + +public: + BoolCoercionRules (BoolType *base) : BaseCoercionRules (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: + BaseCoercionRules::visit (type); + break; + } + } + +private: + BaseType *get_base () override { return base; } + + BoolType *base; +}; + +class IntCoercionRules : public BaseCoercionRules +{ + using Rust::TyTy::BaseCoercionRules::visit; + +public: + IntCoercionRules (IntType *base) : BaseCoercionRules (base), base (base) {} + + void visit (InferType &type) override + { + // cant assign a float inference variable + if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) + { + BaseCoercionRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); + } + + void visit (IntType &type) override + { + if (type.get_int_kind () != base->get_int_kind ()) + { + BaseCoercionRules::visit (type); + return; + } + + resolved + = new IntType (type.get_ref (), type.get_ty_ref (), type.get_int_kind ()); + } + +private: + BaseType *get_base () override { return base; } + + IntType *base; +}; + +class UintCoercionRules : public BaseCoercionRules +{ + using Rust::TyTy::BaseCoercionRules::visit; + +public: + UintCoercionRules (UintType *base) : BaseCoercionRules (base), base (base) {} + + void visit (InferType &type) override + { + // cant assign a float inference variable + if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) + { + BaseCoercionRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); + } + + void visit (UintType &type) override + { + if (type.get_uint_kind () != base->get_uint_kind ()) + { + BaseCoercionRules::visit (type); + return; + } + + resolved = new UintType (type.get_ref (), type.get_ty_ref (), + type.get_uint_kind ()); + } + +private: + BaseType *get_base () override { return base; } + + UintType *base; +}; + +class FloatCoercionRules : public BaseCoercionRules +{ + using Rust::TyTy::BaseCoercionRules::visit; + +public: + FloatCoercionRules (FloatType *base) : BaseCoercionRules (base), base (base) + {} + + void visit (InferType &type) override + { + if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL) + { + BaseCoercionRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); + } + + void visit (FloatType &type) override + { + if (type.get_float_kind () != base->get_float_kind ()) + { + BaseCoercionRules::visit (type); + return; + } + + resolved = new FloatType (type.get_ref (), type.get_ty_ref (), + type.get_float_kind ()); + } + +private: + BaseType *get_base () override { return base; } + + FloatType *base; +}; + +class ADTCoercionRules : public BaseCoercionRules +{ + using Rust::TyTy::BaseCoercionRules::visit; + +public: + ADTCoercionRules (ADTType *base) : BaseCoercionRules (base), base (base) {} + + void visit (ADTType &type) override + { + if (base->get_identifier ().compare (type.get_identifier ()) != 0) + { + BaseCoercionRules::visit (type); + return; + } + + if (base->num_fields () != type.num_fields ()) + { + BaseCoercionRules::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 TupleCoercionRules : public BaseCoercionRules +{ + using Rust::TyTy::BaseCoercionRules::visit; + +public: + TupleCoercionRules (TupleType *base) : BaseCoercionRules (base), base (base) + {} + + void visit (TupleType &type) override + { + if (base->num_fields () != type.num_fields ()) + { + BaseCoercionRules::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 USizeCoercionRules : public BaseCoercionRules +{ + using Rust::TyTy::BaseCoercionRules::visit; + +public: + USizeCoercionRules (USizeType *base) : BaseCoercionRules (base), base (base) + {} + + void visit (InferType &type) override + { + // cant assign a float inference variable + if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) + { + BaseCoercionRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); + } + + void visit (USizeType &type) override { resolved = type.clone (); } + +private: + BaseType *get_base () override { return base; } + + USizeType *base; +}; + +class ISizeCoercionRules : public BaseCoercionRules +{ + using Rust::TyTy::BaseCoercionRules::visit; + +public: + ISizeCoercionRules (ISizeType *base) : BaseCoercionRules (base), base (base) + {} + + void visit (InferType &type) override + { + // cant assign a float inference variable + if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) + { + BaseCoercionRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); + } + + void visit (ISizeType &type) override { resolved = type.clone (); } + +private: + BaseType *get_base () override { return base; } + + ISizeType *base; +}; + +class CharCoercionRules : public BaseCoercionRules +{ + using Rust::TyTy::BaseCoercionRules::visit; + +public: + CharCoercionRules (CharType *base) : BaseCoercionRules (base), base (base) {} + + void visit (InferType &type) override + { + if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) + { + BaseCoercionRules::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 ReferenceCoercionRules : public BaseCoercionRules +{ + using Rust::TyTy::BaseCoercionRules::visit; + +public: + ReferenceCoercionRules (ReferenceType *base) + : BaseCoercionRules (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) + { + BaseCoercionRules::visit (type); + return; + } + + // we can allow for mutability changes here by casting down from mutability + // eg: mut vs const, we cant take a mutable reference from a const + // eg: const vs mut we can take a const reference from a mutable one + if (!base->is_mutable () || (base->is_mutable () == type.is_mutable ())) + { + resolved = new ReferenceType (base->get_ref (), base->get_ty_ref (), + TyVar (base_resolved->get_ref ()), + base->is_mutable ()); + return; + } + + BaseCoercionRules::visit (type); + } + +private: + BaseType *get_base () override { return base; } + + ReferenceType *base; +}; + +class ParamCoercionRules : public BaseCoercionRules +{ + using Rust::TyTy::BaseCoercionRules::visit; + +public: + ParamCoercionRules (ParamType *base) : BaseCoercionRules (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 *coerce (BaseType *other) override final + { + if (base->get_ref () == base->get_ty_ref ()) + return BaseCoercionRules::coerce (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) + { + BaseCoercionRules::visit (type); + return; + } + + resolved = type.clone (); + } + + void visit (InferType &type) override + { + if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) + { + BaseCoercionRules::visit (type); + return; + } + + resolved = base->clone (); + } + +private: + BaseType *get_base () override { return base; } + + ParamType *base; +}; + +class StrCoercionRules : public BaseCoercionRules +{ + // FIXME we will need a enum for the StrType like ByteBuf etc.. + using Rust::TyTy::BaseCoercionRules::visit; + +public: + StrCoercionRules (StrType *base) : BaseCoercionRules (base), base (base) {} + + void visit (StrType &type) override { resolved = type.clone (); } + +private: + BaseType *get_base () override { return base; } + + StrType *base; +}; + +class NeverCoercionRules : public BaseCoercionRules +{ + using Rust::TyTy::BaseCoercionRules::visit; + +public: + NeverCoercionRules (NeverType *base) : BaseCoercionRules (base), base (base) + {} + + virtual void visit (NeverType &type) override { resolved = type.clone (); } + +private: + BaseType *get_base () override { return base; } + + NeverType *base; +}; + +class PlaceholderCoercionRules : public BaseCoercionRules +{ + using Rust::TyTy::BaseCoercionRules::visit; + +public: + PlaceholderCoercionRules (PlaceholderType *base) + : BaseCoercionRules (base), base (base) + {} + +private: + BaseType *get_base () override { return base; } + + PlaceholderType *base; +}; + +} // namespace TyTy +} // namespace Rust + +#endif // RUST_TYTY_COERCION_RULES diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 5db005b..31d7191 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -1081,8 +1081,15 @@ public: return; } + if (base->is_mutable () != type.is_mutable ()) + { + BaseRules::visit (type); + return; + } + resolved = new ReferenceType (base->get_ref (), base->get_ty_ref (), - TyVar (base_resolved->get_ref ())); + TyVar (base_resolved->get_ref ()), + base->is_mutable ()); } private: diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index e2c5f71..16bb01b 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -23,6 +23,7 @@ #include "rust-hir-type-check-type.h" #include "rust-tyty-rules.h" #include "rust-tyty-cmp.h" +#include "rust-tyty-coercion.h" #include "rust-hir-map.h" #include "rust-substitution-mapper.h" @@ -111,6 +112,13 @@ InferType::can_eq (const BaseType *other, bool emit_errors) const } BaseType * +InferType::coerce (BaseType *other) +{ + InferCoercionRules r (this); + return r.coerce (other); +} + +BaseType * InferType::clone () { return new InferType (get_ref (), get_ty_ref (), get_infer_kind (), @@ -173,6 +181,12 @@ ErrorType::can_eq (const BaseType *other, bool emit_errors) const } BaseType * +ErrorType::coerce (BaseType *other) +{ + return this; +} + +BaseType * ErrorType::clone () { return new ErrorType (get_ref (), get_ty_ref (), get_combined_refs ()); @@ -438,6 +452,13 @@ ADTType::unify (BaseType *other) return r.unify (other); } +BaseType * +ADTType::coerce (BaseType *other) +{ + ADTCoercionRules r (this); + return r.coerce (other); +} + bool ADTType::can_eq (const BaseType *other, bool emit_errors) const { @@ -605,6 +626,13 @@ TupleType::unify (BaseType *other) return r.unify (other); } +BaseType * +TupleType::coerce (BaseType *other) +{ + TupleCoercionRules r (this); + return r.coerce (other); +} + bool TupleType::can_eq (const BaseType *other, bool emit_errors) const { @@ -695,6 +723,13 @@ FnType::unify (BaseType *other) return r.unify (other); } +BaseType * +FnType::coerce (BaseType *other) +{ + FnCoercionRules r (this); + return r.coerce (other); +} + bool FnType::can_eq (const BaseType *other, bool emit_errors) const { @@ -896,6 +931,13 @@ FnPtr::unify (BaseType *other) return r.unify (other); } +BaseType * +FnPtr::coerce (BaseType *other) +{ + FnptrCoercionRules r (this); + return r.coerce (other); +} + bool FnPtr::can_eq (const BaseType *other, bool emit_errors) const { @@ -969,6 +1011,13 @@ ArrayType::unify (BaseType *other) return r.unify (other); } +BaseType * +ArrayType::coerce (BaseType *other) +{ + ArrayCoercionRules r (this); + return r.coerce (other); +} + bool ArrayType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1030,6 +1079,13 @@ BoolType::unify (BaseType *other) return r.unify (other); } +BaseType * +BoolType::coerce (BaseType *other) +{ + BoolCoercionRules r (this); + return r.coerce (other); +} + bool BoolType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1082,6 +1138,13 @@ IntType::unify (BaseType *other) return r.unify (other); } +BaseType * +IntType::coerce (BaseType *other) +{ + IntCoercionRules r (this); + return r.coerce (other); +} + bool IntType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1145,6 +1208,13 @@ UintType::unify (BaseType *other) return r.unify (other); } +BaseType * +UintType::coerce (BaseType *other) +{ + UintCoercionRules r (this); + return r.coerce (other); +} + bool UintType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1202,6 +1272,13 @@ FloatType::unify (BaseType *other) return r.unify (other); } +BaseType * +FloatType::coerce (BaseType *other) +{ + FloatCoercionRules r (this); + return r.coerce (other); +} + bool FloatType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1251,6 +1328,13 @@ USizeType::unify (BaseType *other) return r.unify (other); } +BaseType * +USizeType::coerce (BaseType *other) +{ + USizeCoercionRules r (this); + return r.coerce (other); +} + bool USizeType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1289,6 +1373,13 @@ ISizeType::unify (BaseType *other) return r.unify (other); } +BaseType * +ISizeType::coerce (BaseType *other) +{ + ISizeCoercionRules r (this); + return r.coerce (other); +} + bool ISizeType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1327,6 +1418,13 @@ CharType::unify (BaseType *other) return r.unify (other); } +BaseType * +CharType::coerce (BaseType *other) +{ + CharCoercionRules r (this); + return r.coerce (other); +} + bool CharType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1355,7 +1453,8 @@ ReferenceType::accept_vis (TyConstVisitor &vis) const std::string ReferenceType::as_string () const { - return "&" + get_base ()->as_string (); + return std::string ("&") + (is_mutable () ? "mut" : "") + " " + + get_base ()->as_string (); } BaseType * @@ -1365,6 +1464,13 @@ ReferenceType::unify (BaseType *other) return r.unify (other); } +BaseType * +ReferenceType::coerce (BaseType *other) +{ + ReferenceCoercionRules r (this); + return r.coerce (other); +} + bool ReferenceType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1391,7 +1497,7 @@ ReferenceType::get_base () const BaseType * ReferenceType::clone () { - return new ReferenceType (get_ref (), get_ty_ref (), base, + return new ReferenceType (get_ref (), get_ty_ref (), base, is_mutable (), get_combined_refs ()); } @@ -1446,6 +1552,13 @@ ParamType::unify (BaseType *other) return r.unify (other); } +BaseType * +ParamType::coerce (BaseType *other) +{ + ParamCoercionRules r (this); + return r.coerce (other); +} + bool ParamType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1552,6 +1665,13 @@ StrType::unify (BaseType *other) return r.unify (other); } +BaseType * +StrType::coerce (BaseType *other) +{ + StrCoercionRules r (this); + return r.coerce (other); +} + bool StrType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1590,6 +1710,13 @@ NeverType::unify (BaseType *other) return r.unify (other); } +BaseType * +NeverType::coerce (BaseType *other) +{ + NeverCoercionRules r (this); + return r.coerce (other); +} + bool NeverType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1628,6 +1755,13 @@ PlaceholderType::unify (BaseType *other) return r.unify (other); } +BaseType * +PlaceholderType::coerce (BaseType *other) +{ + PlaceholderCoercionRules r (this); + return r.coerce (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 935b943..c0af9f6 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -156,9 +156,20 @@ public: virtual BaseType *unify (BaseType *other) = 0; // similar to unify but does not actually perform type unification but - // determines whether they are compatible + // determines whether they are compatible. Consider the following + // + // fn foo<T>() -> T { ... } + // fn foo() -> i32 { ... } + // + // when the function has been substituted they can be considered equal. + // + // It can also be used to optional emit errors for trait item compatibility + // checks virtual bool can_eq (const BaseType *other, bool emit_errors) const = 0; + // this is the base coercion interface for types + virtual BaseType *coerce (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 @@ -279,6 +290,8 @@ public: bool can_eq (const BaseType *other, bool emit_errors) const override final; + BaseType *coerce (BaseType *other) override; + BaseType *clone () final override; InferTypeKind get_infer_kind () const { return infer_kind; } @@ -313,6 +326,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 *clone () final override; @@ -342,6 +356,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 *clone () final override; @@ -428,6 +443,7 @@ public: BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; + BaseType *coerce (BaseType *other) override; bool is_equal (const BaseType &other) const override; @@ -861,6 +877,7 @@ public: BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; + BaseType *coerce (BaseType *other) override; bool is_equal (const BaseType &other) const override; @@ -981,6 +998,7 @@ public: BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; + BaseType *coerce (BaseType *other) override; bool is_equal (const BaseType &other) const override; @@ -1081,6 +1099,7 @@ public: BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; + BaseType *coerce (BaseType *other) override; bool is_equal (const BaseType &other) const override; @@ -1124,6 +1143,7 @@ public: BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; + BaseType *coerce (BaseType *other) override; bool is_equal (const BaseType &other) const override; @@ -1164,6 +1184,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 *clone () final override; }; @@ -1198,6 +1219,7 @@ public: BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; + BaseType *coerce (BaseType *other) override; IntKind get_int_kind () const { return int_kind; } @@ -1239,6 +1261,7 @@ public: BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; + BaseType *coerce (BaseType *other) override; UintKind get_uint_kind () const { return uint_kind; } @@ -1278,6 +1301,7 @@ public: BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; + BaseType *coerce (BaseType *other) override; FloatKind get_float_kind () const { return float_kind; } @@ -1293,22 +1317,12 @@ class USizeType : public BaseType { public: USizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ref, TypeKind::USIZE) - { - // TODO unused; should 'refs' be passed as the last argument to the - // 'BaseType' constructor call? Potential change in behavior (if 'refs' is - // provided by caller)? - (void) refs; - } + : BaseType (ref, ref, TypeKind::USIZE, refs) + {} USizeType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ty_ref, TypeKind::USIZE) - { - // TODO unused; should 'refs' be passed as the last argument to the - // 'BaseType' constructor call? Potential change in behavior (if 'refs' is - // provided by caller)? - (void) refs; - } + : BaseType (ref, ty_ref, TypeKind::USIZE, refs) + {} void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; @@ -1319,6 +1333,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 *clone () final override; }; @@ -1327,22 +1342,12 @@ class ISizeType : public BaseType { public: ISizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ref, TypeKind::ISIZE) - { - // TODO unused; should 'refs' be passed as the last argument to the - // 'BaseType' constructor call? Potential change in behavior (if 'refs' is - // provided by caller)? - (void) refs; - } + : BaseType (ref, ref, TypeKind::ISIZE, refs) + {} ISizeType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ty_ref, TypeKind::ISIZE) - { - // TODO unused; should 'refs' be passed as the last argument to the - // 'BaseType' constructor call? Potential change in behavior (if 'refs' is - // provided by caller)? - (void) refs; - } + : BaseType (ref, ty_ref, TypeKind::ISIZE, refs) + {} void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; @@ -1353,6 +1358,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 *clone () final override; }; @@ -1361,22 +1367,12 @@ class CharType : public BaseType { public: CharType (HirId ref, std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ref, TypeKind::CHAR) - { - // TODO unused; should 'refs' be passed as the last argument to the - // 'BaseType' constructor call? Potential change in behavior (if 'refs' is - // provided by caller)? - (void) refs; - } + : BaseType (ref, ref, TypeKind::CHAR, refs) + {} CharType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ty_ref, TypeKind::CHAR) - { - // TODO unused; should 'refs' be passed as the last argument to the - // 'BaseType' constructor call? Potential change in behavior (if 'refs' is - // provided by caller)? - (void) refs; - } + : BaseType (ref, ty_ref, TypeKind::CHAR, refs) + {} void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; @@ -1387,6 +1383,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 *clone () final override; }; @@ -1394,25 +1391,15 @@ public: class ReferenceType : public BaseType { public: - ReferenceType (HirId ref, TyVar base, + ReferenceType (HirId ref, TyVar base, bool is_mut, std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ref, TypeKind::REF), base (base) - { - // TODO unused; should 'refs' be passed as the last argument to the - // 'BaseType' constructor call? Potential change in behavior (if 'refs' is - // provided by caller)? - (void) refs; - } + : BaseType (ref, ref, TypeKind::REF, refs), base (base), is_mut (is_mut) + {} - ReferenceType (HirId ref, HirId ty_ref, TyVar base, + ReferenceType (HirId ref, HirId ty_ref, TyVar base, bool is_mut, std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ty_ref, TypeKind::REF), base (base) - { - // TODO unused; should 'refs' be passed as the last argument to the - // 'BaseType' constructor call? Potential change in behavior (if 'refs' is - // provided by caller)? - (void) refs; - } + : BaseType (ref, ty_ref, TypeKind::REF, refs), base (base), is_mut (is_mut) + {} BaseType *get_base () const; @@ -1425,6 +1412,7 @@ public: BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; + BaseType *coerce (BaseType *other) override; bool is_equal (const BaseType &other) const override; @@ -1437,30 +1425,23 @@ public: ReferenceType *handle_substitions (SubstitutionArgumentMappings mappings); + bool is_mutable () const { return is_mut; } + private: TyVar base; + bool is_mut; }; class StrType : public BaseType { public: StrType (HirId ref, std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ref, TypeKind::STR) - { - // TODO unused; should 'refs' be passed as the last argument to the - // 'BaseType' constructor call? Potential change in behavior (if 'refs' is - // provided by caller)? - (void) refs; - } + : BaseType (ref, ref, TypeKind::STR, refs) + {} StrType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ty_ref, TypeKind::STR) - { - // TODO unused; should 'refs' be passed as the last argument to the - // 'BaseType' constructor call? Potential change in behavior (if 'refs' is - // provided by caller)? - (void) refs; - } + : BaseType (ref, ty_ref, TypeKind::STR, refs) + {} std::string get_name () const override final { return as_string (); } @@ -1471,6 +1452,7 @@ public: BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; + BaseType *coerce (BaseType *other) override; bool is_equal (const BaseType &other) const override; @@ -1505,6 +1487,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 *clone () final override; @@ -1534,6 +1517,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 *clone () final override; diff --git a/gcc/testsuite/rust/compile/reference1.rs b/gcc/testsuite/rust/compile/reference1.rs new file mode 100644 index 0000000..3d97926 --- /dev/null +++ b/gcc/testsuite/rust/compile/reference1.rs @@ -0,0 +1,5 @@ +fn main() { + let a = &123; + let b: &mut i32 = a; + // { dg-error "expected .&mut i32. got .& i32." "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/rust/compile/torture/coercion1.rs b/gcc/testsuite/rust/compile/torture/coercion1.rs new file mode 100644 index 0000000..3bfa938 --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/coercion1.rs @@ -0,0 +1,11 @@ +pub fn main() { + let a: &i32 = &123; + // { dg-warning "unused name" "" { target *-*-* } .-1 } + let b: &mut i32 = &mut 123; + + let c: &i32 = &mut 123; + // { dg-warning "unused name" "" { target *-*-* } .-1 } + + let d: &i32 = b; + // { dg-warning "unused name" "" { target *-*-* } .-1 } +} |