@@ -134,6 +134,7 @@ GRS_OBJS = \
rust/rust-hir-path-probe.o \
rust/rust-coercion.o \
rust/rust-casts.o \
+ rust/rust-unify.o \
rust/rust-hir-type-check-base.o \
rust/rust-autoderef.o \
rust/rust-substitution-mapper.o \
@@ -26,6 +26,7 @@
#include "rust-compile-block.h"
#include "rust-compile-implitem.h"
#include "rust-constexpr.h"
+#include "rust-unify.h"
#include "rust-gcc.h"
#include "fold-const.h"
@@ -2006,7 +2007,10 @@ CompileExpr::resolve_method_address (TyTy::FnType *fntype, HirId ref,
{
TyTy::BaseType *infer_impl_call
= candidate_call->infer_substitions (expr_locus);
- monomorphized = infer_impl_call->unify (fntype);
+ monomorphized = Resolver::UnifyRules::Resolve (
+ TyTy::TyWithLocation (infer_impl_call),
+ TyTy::TyWithLocation (fntype), expr_locus, true /* commit */,
+ true /* emit_errors */);
}
return CompileInherentImplItem::Compile (impl_item, ctx, monomorphized);
@@ -18,6 +18,7 @@
#include "rust-hir-type-check-base.h"
#include "rust-coercion.h"
+#include "rust-unify.h"
namespace Rust {
namespace Resolver {
@@ -218,7 +219,10 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver,
// we might be able to replace this with a can_eq because we default
// back to a final unity anyway
rust_debug ("coerce_borrowed_pointer -- unify");
- TyTy::BaseType *result = receiver->unify (expected);
+ TyTy::BaseType *result
+ = UnifyRules::Resolve (TyTy::TyWithLocation (receiver),
+ TyTy::TyWithLocation (expected), locus,
+ true /* commit */, true /* emit_errors */);
return CoercionResult{{}, result};
}
}
@@ -22,6 +22,7 @@
#include "rust-hir-type-check-expr.h"
#include "rust-hir-type-check-implitem.h"
#include "rust-coercion.h"
+#include "rust-unify.h"
#include "rust-casts.h"
namespace Rust {
@@ -359,18 +360,8 @@ TypeCheckBase::unify_site (HirId id, TyTy::TyWithLocation lhs,
rust_debug ("unify_site id={%u} expected={%s} expr={%s}", id,
expected->debug_str ().c_str (), expr->debug_str ().c_str ());
- TyTy::BaseType *unified = expected->unify (expr);
- if (unified->get_kind () == TyTy::TypeKind::ERROR)
- {
- RichLocation r (unify_locus);
- r.add_range (lhs.get_locus ());
- r.add_range (rhs.get_locus ());
- rust_error_at (r, "expected %<%s%> got %<%s%>",
- expected->get_name ().c_str (),
- expr->get_name ().c_str ());
- }
-
- return unified;
+ return UnifyRules::Resolve (lhs, rhs, unify_locus, true /*commit*/,
+ true /*emit_error*/);
}
TyTy::BaseType *
deleted file mode 100644
@@ -1,1406 +0,0 @@
-// Copyright (C) 2020-2023 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_RULES
-#define RUST_TYTY_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"
-
-namespace Rust {
-namespace TyTy {
-
-/* Rules specify how to unify two Ty. For example, the result of unifying the
- two tuples (u64, A) and (B, i64) would be (u64, i64).
-
- Performing a unification requires a double dispatch. To illustrate, suppose
- we want to unify `ty1` and `ty2`. Here's what it looks like:
- 1. The caller calls `ty1.unify(ty2)`. This is the first dispatch.
- 2. `ty1` creates a rule specific to its type(e.g. TupleRules).
- 3. The rule calls `ty2.accept_vis(rule)`. This is the second dispatch.
- 4. `ty2` calls `rule.visit(*this)`, which will method-overload to the
- correct implementation at compile time.
-
- The nice thing about Rules is that they seperate unification logic from the
- representation of Ty. To support unifying a new Ty, implement its
- `accept_vis` and `unify` method to pass the unification request to Rules.
- Then, create a new `XXXRules` class and implement one `visit` method for
- every Ty it can unify with. */
-class BaseRules : public TyVisitor
-{
-public:
- virtual ~BaseRules () {}
-
- /* Unify two ty. Returns a pointer to the newly-created unified ty, or nullptr
- if the two types cannot be unified. The caller is responsible for releasing
- the memory of the returned ty.
-
- This method is meant to be used internally by Ty. If you're trying to unify
- two ty, you can simply call `unify` on ty themselves. */
- virtual BaseType *unify (BaseType *other)
- {
- if (other->get_kind () == TypeKind::PARAM)
- {
- ParamType *p = static_cast<ParamType *> (other);
- other = p->resolve ();
- }
- else if (other->get_kind () == TypeKind::PLACEHOLDER)
- {
- PlaceholderType *p = static_cast<PlaceholderType *> (other);
- if (p->can_resolve ())
- {
- other = p->resolve ();
- return get_base ()->unify (other);
- }
- }
- else if (other->get_kind () == TypeKind::PROJECTION)
- {
- ProjectionType *p = static_cast<ProjectionType *> (other);
- other = p->get ();
- return get_base ()->unify (other);
- }
-
- 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);
-
- other->append_reference (resolved->get_ref ());
- other->append_reference (get_base ()->get_ref ());
- get_base ()->append_reference (resolved->get_ref ());
- get_base ()->append_reference (other->get_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 &) override {}
-
- virtual void visit (ADTType &) override {}
-
- virtual void visit (InferType &) override {}
-
- virtual void visit (FnType &) override {}
-
- virtual void visit (FnPtr &) override {}
-
- virtual void visit (ArrayType &) override {}
-
- virtual void visit (SliceType &) override {}
-
- virtual void visit (BoolType &) override {}
-
- virtual void visit (IntType &) override {}
-
- virtual void visit (UintType &) override {}
-
- virtual void visit (USizeType &) override {}
-
- virtual void visit (ISizeType &) override {}
-
- virtual void visit (FloatType &) override {}
-
- virtual void visit (ErrorType &) override {}
-
- virtual void visit (CharType &) override {}
-
- virtual void visit (ReferenceType &) override {}
-
- virtual void visit (PointerType &) override {}
-
- virtual void visit (ParamType &) override {}
-
- virtual void visit (StrType &) override {}
-
- virtual void visit (NeverType &) override {}
-
- virtual void visit (PlaceholderType &) override {}
-
- virtual void visit (ProjectionType &) override {}
-
- virtual void visit (DynamicObjectType &) override {}
-
- virtual void visit (ClosureType &) override {}
-
-protected:
- BaseRules (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 InferRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- InferRules (InferType *base) : BaseRules (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;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (IntType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
- || (base->get_infer_kind ()
- == TyTy::InferType::InferTypeKind::INTEGRAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (UintType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
- || (base->get_infer_kind ()
- == TyTy::InferType::InferTypeKind::INTEGRAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (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;
- }
-
- BaseRules::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;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (FloatType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
- || (base->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (ArrayType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (SliceType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (ADTType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (TupleType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (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;
- }
-
- BaseRules::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;
- }
-
- BaseRules::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;
- }
-
- BaseRules::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;
- }
-
- BaseRules::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;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (DynamicObjectType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (ClosureType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- InferType *base;
-};
-
-class FnRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- FnRules (FnType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (FnType &type) override
- {
- if (base->num_params () != type.num_params ())
- {
- BaseRules::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)
- {
- BaseRules::visit (type);
- return;
- }
- }
-
- auto unified_return
- = base->get_return_type ()->unify (type.get_return_type ());
- if (unified_return == nullptr)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- FnType *base;
-};
-
-class FnptrRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- FnptrRules (FnPtr *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::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)
- {
- BaseRules::visit (type);
- return;
- }
-
- if (base->num_params () != type.num_params ())
- {
- BaseRules::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)
- {
- BaseRules::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)
- {
- BaseRules::visit (type);
- return;
- }
-
- if (base->num_params () != type.num_params ())
- {
- BaseRules::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)
- {
- BaseRules::visit (type);
- return;
- }
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- FnPtr *base;
-};
-
-class ClosureRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- ClosureRules (ClosureType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (ClosureType &type) override
- {
- if (base->get_def_id () != type.get_def_id ())
- {
- BaseRules::visit (type);
- return;
- }
-
- TyTy::BaseType *args_res
- = base->get_parameters ().unify (&type.get_parameters ());
- if (args_res == nullptr || args_res->get_kind () == TypeKind::ERROR)
- {
- BaseRules::visit (type);
- return;
- }
-
- TyTy::BaseType *res
- = base->get_result_type ().unify (&type.get_result_type ());
- if (res == nullptr || res->get_kind () == TypeKind::ERROR)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- ClosureType *base;
-};
-
-class ArrayRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- ArrayRules (ArrayType *base) : BaseRules (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)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved
- = new ArrayType (type.get_ref (), type.get_ty_ref (),
- type.get_ident ().locus, type.get_capacity_expr (),
- TyVar (base_resolved->get_ref ()));
- }
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- ArrayType *base;
-};
-
-class SliceRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- SliceRules (SliceType *base) : BaseRules (base), base (base) {}
-
- void visit (SliceType &type) override
- {
- // check base type
- auto base_resolved
- = base->get_element_type ()->unify (type.get_element_type ());
- if (base_resolved == nullptr)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = new SliceType (type.get_ref (), type.get_ty_ref (),
- type.get_ident ().locus,
- TyVar (base_resolved->get_ref ()));
- }
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- SliceType *base;
-};
-
-class BoolRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- BoolRules (BoolType *base) : BaseRules (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:
- BaseRules::visit (type);
- break;
- }
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- BoolType *base;
-};
-
-class IntRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- IntRules (IntType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- // cant assign a float inference variable
- if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (IntType &type) override
- {
- if (type.get_int_kind () != base->get_int_kind ())
- {
- BaseRules::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 UintRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- UintRules (UintType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- // cant assign a float inference variable
- if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (UintType &type) override
- {
- if (type.get_uint_kind () != base->get_uint_kind ())
- {
- BaseRules::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 FloatRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- FloatRules (FloatType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (FloatType &type) override
- {
- if (type.get_float_kind () != base->get_float_kind ())
- {
- BaseRules::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 ADTRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- ADTRules (ADTType *base) : BaseRules (base), base (base) {}
-
- void visit (ADTType &type) override
- {
- if (base->get_adt_kind () != type.get_adt_kind ())
- {
- BaseRules::visit (type);
- return;
- }
-
- if (base->get_identifier ().compare (type.get_identifier ()) != 0)
- {
- BaseRules::visit (type);
- return;
- }
-
- if (base->number_of_variants () != type.number_of_variants ())
- {
- BaseRules::visit (type);
- return;
- }
-
- for (size_t i = 0; i < type.number_of_variants (); ++i)
- {
- TyTy::VariantDef *a = base->get_variants ().at (i);
- TyTy::VariantDef *b = type.get_variants ().at (i);
-
- if (a->num_fields () != b->num_fields ())
- {
- BaseRules::visit (type);
- return;
- }
-
- for (size_t j = 0; j < a->num_fields (); j++)
- {
- TyTy::StructFieldType *base_field = a->get_field_at_index (j);
- TyTy::StructFieldType *other_field = b->get_field_at_index (j);
-
- 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;
- }
- }
-
- // generic args for the unit-struct case
- if (type.is_unit () && base->is_unit ())
- {
- rust_assert (type.get_num_substitutions ()
- == base->get_num_substitutions ());
-
- for (size_t i = 0; i < type.get_num_substitutions (); i++)
- {
- auto &a = base->get_substs ().at (i);
- auto &b = type.get_substs ().at (i);
-
- auto pa = a.get_param_ty ();
- auto pb = b.get_param_ty ();
-
- auto res = pa->unify (pb);
- if (res->get_kind () == TyTy::TypeKind::ERROR)
- {
- return;
- }
- }
- }
-
- resolved = type.clone ();
- }
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- ADTType *base;
-};
-
-class TupleRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- TupleRules (TupleType *base) : BaseRules (base), base (base) {}
-
- void visit (TupleType &type) override
- {
- if (base->num_fields () != type.num_fields ())
- {
- BaseRules::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 (),
- type.get_ident ().locus, fields);
- }
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- TupleType *base;
-};
-
-class USizeRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- USizeRules (USizeType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- // cant assign a float inference variable
- if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (USizeType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- USizeType *base;
-};
-
-class ISizeRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- ISizeRules (ISizeType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- // cant assign a float inference variable
- if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (ISizeType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- ISizeType *base;
-};
-
-class CharRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- CharRules (CharType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::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 ReferenceRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- ReferenceRules (ReferenceType *base) : BaseRules (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)
- {
- BaseRules::visit (type);
- return;
- }
-
- // rust is permissive about mutablity here you can always go from mutable to
- // immutable but not the otherway round
- bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
- if (!mutability_ok)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = new ReferenceType (base->get_ref (), base->get_ty_ref (),
- TyVar (base_resolved->get_ref ()),
- base->mutability ());
- }
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- ReferenceType *base;
-};
-
-class PointerRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- PointerRules (PointerType *base) : BaseRules (base), base (base) {}
-
- 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)
- {
- BaseRules::visit (type);
- return;
- }
-
- // rust is permissive about mutablity here you can always go from mutable to
- // immutable but not the otherway round
- bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
- if (!mutability_ok)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = new PointerType (base->get_ref (), base->get_ty_ref (),
- TyVar (base_resolved->get_ref ()),
- base->mutability ());
- }
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- PointerType *base;
-};
-
-class ParamRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- ParamRules (ParamType *base) : BaseRules (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 *unify (BaseType *other) override final
- {
- if (!base->can_resolve ())
- return BaseRules::unify (other);
-
- auto lookup = base->resolve ();
- return lookup->unify (other);
- }
-
- void visit (ParamType &type) override
- {
- if (base->get_symbol ().compare (type.get_symbol ()) != 0)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = type.clone ();
- }
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- ParamType *base;
-};
-
-class StrRules : public BaseRules
-{
- // FIXME we will need a enum for the StrType like ByteBuf etc..
- using Rust::TyTy::BaseRules::visit;
-
-public:
- StrRules (StrType *base) : BaseRules (base), base (base) {}
-
- void visit (StrType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- StrType *base;
-};
-
-class NeverRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- NeverRules (NeverType *base) : BaseRules (base), base (base) {}
-
- void visit (NeverType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- NeverType *base;
-};
-
-class PlaceholderRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- PlaceholderRules (PlaceholderType *base) : BaseRules (base), base (base) {}
-
- BaseType *unify (BaseType *other) override final
- {
- if (!base->can_resolve ())
- return BaseRules::unify (other);
-
- BaseType *lookup = base->resolve ();
- return lookup->unify (other);
- }
-
- void visit (PlaceholderType &type) override
- {
- if (base->get_symbol ().compare (type.get_symbol ()) != 0)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = type.clone ();
- }
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- PlaceholderType *base;
-};
-
-class DynamicRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- DynamicRules (DynamicObjectType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- }
-
- void visit (DynamicObjectType &type) override
- {
- if (base->num_specified_bounds () != type.num_specified_bounds ())
- {
- BaseRules::visit (type);
- return;
- }
-
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- if (!base->bounds_compatible (type, ref_locus, true))
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- DynamicObjectType *base;
-};
-
-} // namespace TyTy
-} // namespace Rust
-
-#endif // RUST_TYTY_RULES
@@ -30,7 +30,6 @@
#include "rust-hir-trait-reference.h"
#include "rust-hir-type-bounds.h"
#include "rust-hir-trait-resolve.h"
-#include "rust-tyty-rules.h"
#include "rust-tyty-cmp.h"
#include "options.h"
@@ -376,6 +375,58 @@ BaseType::get_root () const
return root;
}
+BaseType *
+BaseType::destructure ()
+{
+ int recurisve_ops = 0;
+ BaseType *x = this;
+ while (true)
+ {
+ if (recurisve_ops++ >= rust_max_recursion_depth)
+ {
+ rust_error_at (
+ Location (),
+ "%<recursion depth%> count exceeds limit of %i (use "
+ "%<frust-max-recursion-depth=%> to increase the limit)",
+ rust_max_recursion_depth);
+ return new ErrorType (get_ref ());
+ }
+
+ switch (x->get_kind ())
+ {
+ case TyTy::TypeKind::PARAM: {
+ TyTy::ParamType *p = static_cast<TyTy::ParamType *> (x);
+ TyTy::BaseType *pr = p->resolve ();
+ if (pr == x)
+ return pr;
+
+ x = pr;
+ }
+ break;
+
+ case TyTy::TypeKind::PLACEHOLDER: {
+ TyTy::PlaceholderType *p = static_cast<TyTy::PlaceholderType *> (x);
+ if (!p->can_resolve ())
+ return p;
+
+ x = p->resolve ();
+ }
+ break;
+
+ case TyTy::TypeKind::PROJECTION: {
+ TyTy::ProjectionType *p = static_cast<TyTy::ProjectionType *> (x);
+ x = p->get ();
+ }
+ break;
+
+ default:
+ return x;
+ }
+ }
+
+ return x;
+}
+
const BaseType *
BaseType::destructure () const
{
@@ -397,14 +448,20 @@ BaseType::destructure () const
{
case TyTy::TypeKind::PARAM: {
const TyTy::ParamType *p = static_cast<const TyTy::ParamType *> (x);
- x = p->resolve ();
+ const TyTy::BaseType *pr = p->resolve ();
+ if (pr == x)
+ return pr;
+
+ x = pr;
}
break;
case TyTy::TypeKind::PLACEHOLDER: {
const TyTy::PlaceholderType *p
= static_cast<const TyTy::PlaceholderType *> (x);
- rust_assert (p->can_resolve ());
+ if (!p->can_resolve ())
+ return p;
+
x = p->resolve ();
}
break;
@@ -512,13 +569,6 @@ InferType::as_string () const
return "<infer::error>";
}
-BaseType *
-InferType::unify (BaseType *other)
-{
- InferRules r (this);
- return r.unify (other);
-}
-
bool
InferType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -637,12 +687,6 @@ ErrorType::as_string () const
return "<tyty::error>";
}
-BaseType *
-ErrorType::unify (BaseType *other)
-{
- return this;
-}
-
bool
ErrorType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1009,13 +1053,6 @@ ADTType::as_string () const
return identifier + subst_as_string () + "{" + variants_buffer + "}";
}
-BaseType *
-ADTType::unify (BaseType *other)
-{
- ADTRules r (this);
- return r.unify (other);
-}
-
bool
ADTType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1278,13 +1315,6 @@ TupleType::get_field (size_t index) const
return fields.at (index).get_tyty ();
}
-BaseType *
-TupleType::unify (BaseType *other)
-{
- TupleRules r (this);
- return r.unify (other);
-}
-
bool
TupleType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1385,13 +1415,6 @@ FnType::as_string () const
return "fn" + subst_as_string () + " (" + params_str + ") -> " + ret_str;
}
-BaseType *
-FnType::unify (BaseType *other)
-{
- FnRules r (this);
- return r.unify (other);
-}
-
bool
FnType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1616,13 +1639,6 @@ FnPtr::as_string () const
return "fnptr (" + params_str + ") -> " + get_return_type ()->as_string ();
}
-BaseType *
-FnPtr::unify (BaseType *other)
-{
- FnptrRules r (this);
- return r.unify (other);
-}
-
bool
FnPtr::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1696,13 +1712,6 @@ ClosureType::as_string () const
return "|" + params_buf + "| {" + result_type.get_tyty ()->as_string () + "}";
}
-BaseType *
-ClosureType::unify (BaseType *other)
-{
- ClosureRules r (this);
- return r.unify (other);
-}
-
bool
ClosureType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1812,13 +1821,6 @@ ArrayType::as_string () const
return "[" + get_element_type ()->as_string () + ":" + "CAPACITY" + "]";
}
-BaseType *
-ArrayType::unify (BaseType *other)
-{
- ArrayRules r (this);
- return r.unify (other);
-}
-
bool
ArrayType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1895,13 +1897,6 @@ SliceType::as_string () const
return "[" + get_element_type ()->as_string () + "]";
}
-BaseType *
-SliceType::unify (BaseType *other)
-{
- SliceRules r (this);
- return r.unify (other);
-}
-
bool
SliceType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2006,13 +2001,6 @@ BoolType::as_string () const
return "bool";
}
-BaseType *
-BoolType::unify (BaseType *other)
-{
- BoolRules r (this);
- return r.unify (other);
-}
-
bool
BoolType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2094,13 +2082,6 @@ IntType::as_string () const
return "__unknown_int_type";
}
-BaseType *
-IntType::unify (BaseType *other)
-{
- IntRules r (this);
- return r.unify (other);
-}
-
bool
IntType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2200,13 +2181,6 @@ UintType::as_string () const
return "__unknown_uint_type";
}
-BaseType *
-UintType::unify (BaseType *other)
-{
- UintRules r (this);
- return r.unify (other);
-}
-
bool
UintType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2306,13 +2280,6 @@ FloatType::as_string () const
return "__unknown_float_type";
}
-BaseType *
-FloatType::unify (BaseType *other)
-{
- FloatRules r (this);
- return r.unify (other);
-}
-
bool
FloatType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2389,13 +2356,6 @@ USizeType::as_string () const
return "usize";
}
-BaseType *
-USizeType::unify (BaseType *other)
-{
- USizeRules r (this);
- return r.unify (other);
-}
-
bool
USizeType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2461,13 +2421,6 @@ ISizeType::as_string () const
return "isize";
}
-BaseType *
-ISizeType::unify (BaseType *other)
-{
- ISizeRules r (this);
- return r.unify (other);
-}
-
bool
ISizeType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2533,13 +2486,6 @@ CharType::as_string () const
return "char";
}
-BaseType *
-CharType::unify (BaseType *other)
-{
- CharRules r (this);
- return r.unify (other);
-}
-
bool
CharType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2655,13 +2601,6 @@ ReferenceType::get_name () const
+ get_base ()->get_name ();
}
-BaseType *
-ReferenceType::unify (BaseType *other)
-{
- ReferenceRules r (this);
- return r.unify (other);
-}
-
bool
ReferenceType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2821,13 +2760,6 @@ PointerType::get_name () const
+ get_base ()->get_name ();
}
-BaseType *
-PointerType::unify (BaseType *other)
-{
- PointerRules r (this);
- return r.unify (other);
-}
-
bool
PointerType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2964,13 +2896,6 @@ ParamType::get_name () const
return resolve ()->get_name ();
}
-BaseType *
-ParamType::unify (BaseType *other)
-{
- ParamRules r (this);
- return r.unify (other);
-}
-
bool
ParamType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -3130,13 +3055,6 @@ StrType::as_string () const
return "str";
}
-BaseType *
-StrType::unify (BaseType *other)
-{
- StrRules r (this);
- return r.unify (other);
-}
-
bool
StrType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -3202,13 +3120,6 @@ NeverType::as_string () const
return "!";
}
-BaseType *
-NeverType::unify (BaseType *other)
-{
- NeverRules r (this);
- return r.unify (other);
-}
-
bool
NeverType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -3295,13 +3206,6 @@ PlaceholderType::as_string () const
+ ">";
}
-BaseType *
-PlaceholderType::unify (BaseType *other)
-{
- PlaceholderRules r (this);
- return r.unify (other);
-}
-
bool
PlaceholderType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -3465,12 +3369,6 @@ ProjectionType::as_string () const
return "<Projection=" + subst_as_string () + "::" + base->as_string () + ">";
}
-BaseType *
-ProjectionType::unify (BaseType *other)
-{
- return base->unify (other);
-}
-
bool
ProjectionType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -3602,13 +3500,6 @@ DynamicObjectType::as_string () const
return "dyn [" + raw_bounds_as_string () + "]";
}
-BaseType *
-DynamicObjectType::unify (BaseType *other)
-{
- DynamicRules r (this);
- return r.unify (other);
-}
-
bool
DynamicObjectType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -105,11 +105,6 @@ public:
virtual std::string get_name () const = 0;
- // Unify two types. Returns a pointer to the newly-created unified ty, or
- // nullptr if the two ty cannot be unified. The caller is responsible for
- // releasing the memory of the returned ty.
- virtual BaseType *unify (BaseType *other) = 0;
-
// similar to unify but does not actually perform type unification but
// determines whether they are compatible. Consider the following
//
@@ -177,6 +172,7 @@ public:
// This will get the monomorphized type from Params, Placeholders or
// Projections if available or error
+ BaseType *destructure ();
const BaseType *destructure () const;
const RustIdent &get_ident () const;
@@ -221,8 +217,6 @@ public:
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
-
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
@@ -255,7 +249,6 @@ public:
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
@@ -284,7 +277,6 @@ public:
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
@@ -361,7 +353,6 @@ public:
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -598,7 +589,6 @@ public:
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -738,7 +728,6 @@ public:
std::string get_identifier () const { return identifier; }
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -858,7 +847,6 @@ public:
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -938,7 +926,6 @@ public:
std::string as_string () const override;
std::string get_name () const override final { return as_string (); }
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -1007,7 +994,6 @@ public:
std::string get_name () const override final { return as_string (); }
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -1055,7 +1041,6 @@ public:
std::string get_name () const override final { return as_string (); }
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -1089,7 +1074,6 @@ public:
std::string get_name () const override final;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
@@ -1120,7 +1104,6 @@ public:
std::string get_name () const override final;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
IntKind get_int_kind () const;
@@ -1159,7 +1142,6 @@ public:
std::string get_name () const override final;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
UintKind get_uint_kind () const;
@@ -1194,7 +1176,6 @@ public:
std::string as_string () const override;
std::string get_name () const override final;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
FloatKind get_float_kind () const;
@@ -1222,7 +1203,6 @@ public:
std::string as_string () const override;
std::string get_name () const override final;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
@@ -1243,7 +1223,6 @@ public:
std::string as_string () const override;
std::string get_name () const override final;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
@@ -1263,7 +1242,6 @@ public:
std::string as_string () const override;
std::string get_name () const override final;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
@@ -1284,7 +1262,6 @@ public:
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -1311,7 +1288,6 @@ public:
std::string get_name () const override final;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -1354,7 +1330,6 @@ public:
std::string as_string () const override;
std::string get_name () const override final;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -1401,7 +1376,6 @@ public:
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
@@ -1428,7 +1402,6 @@ public:
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
@@ -1478,7 +1451,6 @@ public:
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
@@ -1524,7 +1496,6 @@ public:
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
new file mode 100644
@@ -0,0 +1,1640 @@
+// Copyright (C) 2020-2022 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/>.
+
+#include "rust-unify.h"
+
+namespace Rust {
+namespace Resolver {
+
+UnifyRules::UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
+ Location locus, bool commit_flag, bool emit_error)
+ : lhs (lhs), rhs (rhs), locus (locus), commit_flag (commit_flag),
+ emit_error (emit_error), mappings (*Analysis::Mappings::get ()),
+ context (*TypeCheckContext::get ())
+{}
+
+TyTy::BaseType *
+UnifyRules::Resolve (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
+ Location locus, bool commit_flag, bool emit_error)
+{
+ UnifyRules r (lhs, rhs, locus, commit_flag, emit_error);
+ TyTy::BaseType *result = r.go ();
+
+ if (r.commit_flag)
+ r.commit (result);
+
+ bool failed = result->get_kind () == TyTy::TypeKind::ERROR;
+ if (failed && r.emit_error)
+ r.emit_type_mismatch ();
+
+ return result;
+}
+
+TyTy::BaseType *
+UnifyRules::get_base ()
+{
+ return lhs.get_ty ()->destructure ();
+}
+
+TyTy::BaseType *
+UnifyRules::get_other ()
+{
+ return rhs.get_ty ()->destructure ();
+}
+
+void
+UnifyRules::commit (TyTy::BaseType *resolved)
+{
+ resolved->append_reference (get_base ()->get_ref ());
+ resolved->append_reference (get_other ()->get_ref ());
+ for (auto ref : get_base ()->get_combined_refs ())
+ resolved->append_reference (ref);
+ for (auto ref : get_other ()->get_combined_refs ())
+ resolved->append_reference (ref);
+
+ get_other ()->append_reference (resolved->get_ref ());
+ get_other ()->append_reference (get_base ()->get_ref ());
+ get_base ()->append_reference (resolved->get_ref ());
+ get_base ()->append_reference (get_other ()->get_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<TyTy::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)
+ {
+ auto node = Analysis::NodeMapping (mappings.get_current_crate (),
+ UNKNOWN_NODEID, ref,
+ UNKNOWN_LOCAL_DEFID);
+ context.insert_type (node, resolved->clone ());
+ }
+ }
+ }
+}
+
+void
+UnifyRules::emit_type_mismatch () const
+{
+ TyTy::BaseType *expected = lhs.get_ty ();
+ TyTy::BaseType *expr = rhs.get_ty ();
+
+ RichLocation r (locus);
+ r.add_range (lhs.get_locus ());
+ r.add_range (rhs.get_locus ());
+ rust_error_at (r, "expected %<%s%> got %<%s%>",
+ expected->get_name ().c_str (), expr->get_name ().c_str ());
+}
+
+TyTy::BaseType *
+UnifyRules::go ()
+{
+ TyTy::BaseType *ltype = lhs.get_ty ();
+ TyTy::BaseType *rtype = rhs.get_ty ();
+
+ ltype = lhs.get_ty ()->destructure ();
+ rtype = rhs.get_ty ()->destructure ();
+
+ rust_debug ("unify::go ltype={%s} rtype={%s}", ltype->debug_str ().c_str (),
+ rtype->debug_str ().c_str ());
+
+ switch (ltype->get_kind ())
+ {
+ case TyTy::INFER:
+ return expect_inference_variable (static_cast<TyTy::InferType *> (ltype),
+ rtype);
+
+ case TyTy::ADT:
+ return expect_adt (static_cast<TyTy::ADTType *> (ltype), rtype);
+
+ case TyTy::STR:
+ return expect_str (static_cast<TyTy::StrType *> (ltype), rtype);
+
+ case TyTy::REF:
+ return expect_reference (static_cast<TyTy::ReferenceType *> (ltype),
+ rtype);
+
+ case TyTy::POINTER:
+ return expect_pointer (static_cast<TyTy::PointerType *> (ltype), rtype);
+
+ case TyTy::PARAM:
+ return expect_param (static_cast<TyTy::ParamType *> (ltype), rtype);
+
+ case TyTy::ARRAY:
+ return expect_array (static_cast<TyTy::ArrayType *> (ltype), rtype);
+
+ case TyTy::SLICE:
+ return expect_slice (static_cast<TyTy::SliceType *> (ltype), rtype);
+
+ case TyTy::FNDEF:
+ return expect_fndef (static_cast<TyTy::FnType *> (ltype), rtype);
+
+ case TyTy::FNPTR:
+ return expect_fnptr (static_cast<TyTy::FnPtr *> (ltype), rtype);
+
+ case TyTy::TUPLE:
+ return expect_tuple (static_cast<TyTy::TupleType *> (ltype), rtype);
+
+ case TyTy::BOOL:
+ return expect_bool (static_cast<TyTy::BoolType *> (ltype), rtype);
+
+ case TyTy::CHAR:
+ return expect_char (static_cast<TyTy::CharType *> (ltype), rtype);
+
+ case TyTy::INT:
+ return expect_int (static_cast<TyTy::IntType *> (ltype), rtype);
+
+ case TyTy::UINT:
+ return expect_uint (static_cast<TyTy::UintType *> (ltype), rtype);
+
+ case TyTy::FLOAT:
+ return expect_float (static_cast<TyTy::FloatType *> (ltype), rtype);
+
+ case TyTy::USIZE:
+ return expect_usize (static_cast<TyTy::USizeType *> (ltype), rtype);
+
+ case TyTy::ISIZE:
+ return expect_isize (static_cast<TyTy::ISizeType *> (ltype), rtype);
+
+ case TyTy::NEVER:
+ return expect_never (static_cast<TyTy::NeverType *> (ltype), rtype);
+
+ case TyTy::PLACEHOLDER:
+ return expect_placeholder (static_cast<TyTy::PlaceholderType *> (ltype),
+ rtype);
+
+ case TyTy::PROJECTION:
+ return expect_projection (static_cast<TyTy::ProjectionType *> (ltype),
+ rtype);
+
+ case TyTy::DYNAMIC:
+ return expect_dyn (static_cast<TyTy::DynamicObjectType *> (ltype), rtype);
+
+ case TyTy::CLOSURE:
+ return expect_closure (static_cast<TyTy::ClosureType *> (ltype), rtype);
+
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_inference_variable (TyTy::InferType *ltype,
+ TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ switch (ltype->get_infer_kind ())
+ {
+ case TyTy::InferType::InferTypeKind::GENERAL:
+ return rtype->clone ();
+
+ case TyTy::InferType::InferTypeKind::INTEGRAL: {
+ bool is_valid = r->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::INTEGRAL
+ || r->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return rtype->clone ();
+ }
+ break;
+
+ case TyTy::InferType::InferTypeKind::FLOAT: {
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT
+ || r->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return rtype->clone ();
+ }
+ break;
+ }
+ }
+ break;
+
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::USIZE:
+ case TyTy::ISIZE: {
+ bool is_valid = (ltype->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::GENERAL)
+ || (ltype->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::INTEGRAL);
+ if (is_valid)
+ return rtype->clone ();
+ }
+ break;
+
+ case TyTy::FLOAT: {
+ bool is_valid = (ltype->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::GENERAL)
+ || (ltype->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::FLOAT);
+ if (is_valid)
+ return rtype->clone ();
+ }
+ break;
+
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE: {
+ bool is_valid = (ltype->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ return rtype->clone ();
+ }
+ break;
+
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::ADT: {
+ TyTy::ADTType &type = *static_cast<TyTy::ADTType *> (rtype);
+ if (ltype->get_adt_kind () != type.get_adt_kind ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ if (ltype->get_identifier ().compare (type.get_identifier ()) != 0)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ if (ltype->number_of_variants () != type.number_of_variants ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ for (size_t i = 0; i < type.number_of_variants (); ++i)
+ {
+ TyTy::VariantDef *a = ltype->get_variants ().at (i);
+ TyTy::VariantDef *b = type.get_variants ().at (i);
+
+ if (a->num_fields () != b->num_fields ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ for (size_t j = 0; j < a->num_fields (); j++)
+ {
+ TyTy::StructFieldType *base_field = a->get_field_at_index (j);
+ TyTy::StructFieldType *other_field = b->get_field_at_index (j);
+
+ TyTy::BaseType *this_field_ty = base_field->get_field_type ();
+ TyTy::BaseType *other_field_ty = other_field->get_field_type ();
+
+ TyTy::BaseType *unified_ty
+ = UnifyRules::Resolve (TyTy::TyWithLocation (this_field_ty),
+ TyTy::TyWithLocation (other_field_ty),
+ locus, commit_flag,
+ false /* emit_error */);
+ if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+ }
+ }
+
+ // generic args for the unit-struct case
+ if (type.is_unit () && ltype->is_unit ())
+ {
+ rust_assert (type.get_num_substitutions ()
+ == ltype->get_num_substitutions ());
+
+ for (size_t i = 0; i < type.get_num_substitutions (); i++)
+ {
+ auto &a = ltype->get_substs ().at (i);
+ auto &b = type.get_substs ().at (i);
+
+ auto pa = a.get_param_ty ();
+ auto pb = b.get_param_ty ();
+
+ auto res
+ = UnifyRules::Resolve (TyTy::TyWithLocation (pa),
+ TyTy::TyWithLocation (pb), locus,
+ commit_flag, false /* emit_error */);
+ if (res->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+ }
+ }
+
+ return type.clone ();
+ }
+ break;
+
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::FLOAT:
+ case TyTy::USIZE:
+ case TyTy::ISIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::STR:
+ return rtype->clone ();
+
+ case TyTy::ADT:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::FLOAT:
+ case TyTy::USIZE:
+ case TyTy::ISIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::REF: {
+ TyTy::ReferenceType &type = *static_cast<TyTy::ReferenceType *> (rtype);
+ auto base_type = ltype->get_base ();
+ auto other_base_type = type.get_base ();
+
+ TyTy::BaseType *base_resolved
+ = UnifyRules::Resolve (TyTy::TyWithLocation (base_type),
+ TyTy::TyWithLocation (other_base_type), locus,
+ commit_flag, false /* emit_error */);
+ if (base_resolved->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ // rust is permissive about mutablity here you can always go from
+ // mutable to immutable but not the otherway round
+ bool mutability_ok = ltype->is_mutable () ? type.is_mutable () : true;
+ if (!mutability_ok)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ return new TyTy::ReferenceType (ltype->get_ref (), ltype->get_ty_ref (),
+ TyTy::TyVar (base_resolved->get_ref ()),
+ ltype->mutability ());
+ }
+ break;
+
+ case TyTy::STR:
+ case TyTy::ADT:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::FLOAT:
+ case TyTy::USIZE:
+ case TyTy::ISIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::POINTER: {
+ TyTy::PointerType &type = *static_cast<TyTy::PointerType *> (rtype);
+ auto base_type = ltype->get_base ();
+ auto other_base_type = type.get_base ();
+
+ TyTy::BaseType *base_resolved
+ = UnifyRules::Resolve (TyTy::TyWithLocation (base_type),
+ TyTy::TyWithLocation (other_base_type), locus,
+ commit_flag, false /* emit_error */);
+ if (base_resolved->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ // rust is permissive about mutablity here you can always go from
+ // mutable to immutable but not the otherway round
+ bool mutability_ok = ltype->is_mutable () ? type.is_mutable () : true;
+ if (!mutability_ok)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ return new TyTy::PointerType (ltype->get_ref (), ltype->get_ty_ref (),
+ TyTy::TyVar (base_resolved->get_ref ()),
+ ltype->mutability ());
+ }
+ break;
+
+ case TyTy::STR:
+ case TyTy::ADT:
+ case TyTy::REF:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::FLOAT:
+ case TyTy::USIZE:
+ case TyTy::ISIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::PARAM: {
+ TyTy::ParamType &type = *static_cast<TyTy::ParamType *> (rtype);
+ // bool symbol_matches
+ // = ltype->get_symbol ().compare (type.get_symbol ()) == 0;
+ // // TODO
+ // // I think rustc checks a debruinj index
+ // if (symbol_matches)
+ // {
+ // return type.clone ();
+ // }
+
+ // matching symbol is not going to work when we mix symbol's and have
+ // nested generics
+
+ // bounds match? FIXME
+
+ return type.clone ();
+ }
+ break;
+
+ case TyTy::POINTER:
+ case TyTy::STR:
+ case TyTy::ADT:
+ case TyTy::REF:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::FLOAT:
+ case TyTy::USIZE:
+ case TyTy::ISIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::ARRAY: {
+ TyTy::ArrayType &type = *static_cast<TyTy::ArrayType *> (rtype);
+ TyTy::BaseType *element_unify = UnifyRules::Resolve (
+ TyTy::TyWithLocation (ltype->get_element_type ()),
+ TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag,
+ false /* emit_error*/);
+
+ if (element_unify->get_kind () != TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ArrayType (type.get_ref (), type.get_ty_ref (),
+ type.get_ident ().locus,
+ type.get_capacity_expr (),
+ TyTy::TyVar (
+ element_unify->get_ref ()));
+ }
+ }
+ break;
+
+ case TyTy::PARAM:
+ case TyTy::POINTER:
+ case TyTy::STR:
+ case TyTy::ADT:
+ case TyTy::REF:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::FLOAT:
+ case TyTy::USIZE:
+ case TyTy::ISIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::SLICE: {
+ TyTy::SliceType &type = *static_cast<TyTy::SliceType *> (rtype);
+ TyTy::BaseType *element_unify = UnifyRules::Resolve (
+ TyTy::TyWithLocation (ltype->get_element_type ()),
+ TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag,
+ false /* emit_error*/);
+
+ if (element_unify->get_kind () != TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::SliceType (type.get_ref (), type.get_ty_ref (),
+ type.get_ident ().locus,
+ TyTy::TyVar (
+ element_unify->get_ref ()));
+ }
+ }
+ break;
+
+ case TyTy::PARAM:
+ case TyTy::POINTER:
+ case TyTy::STR:
+ case TyTy::ADT:
+ case TyTy::REF:
+ case TyTy::ARRAY:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::FLOAT:
+ case TyTy::USIZE:
+ case TyTy::ISIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::FNDEF: {
+ TyTy::FnType &type = *static_cast<TyTy::FnType *> (rtype);
+ if (ltype->num_params () != type.num_params ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ for (size_t i = 0; i < ltype->num_params (); i++)
+ {
+ auto a = ltype->param_at (i).second;
+ auto b = type.param_at (i).second;
+
+ auto unified_param
+ = UnifyRules::Resolve (TyTy::TyWithLocation (a),
+ TyTy::TyWithLocation (b), locus,
+ commit_flag, false /* emit_errors */);
+ if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+ }
+
+ auto unified_return
+ = UnifyRules::Resolve (TyTy::TyWithLocation (
+ ltype->get_return_type ()),
+ TyTy::TyWithLocation (type.get_return_type ()),
+ locus, commit_flag, false /* emit_errors */);
+ if (unified_return->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::FLOAT:
+ case TyTy::ISIZE:
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNPTR:
+ case TyTy::UINT:
+ case TyTy::USIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::FNPTR: {
+ TyTy::FnPtr &type = *static_cast<TyTy::FnPtr *> (rtype);
+ if (ltype->num_params () != type.num_params ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ for (size_t i = 0; i < ltype->num_params (); i++)
+ {
+ auto a = ltype->param_at (i);
+ auto b = type.param_at (i);
+
+ auto unified_param
+ = UnifyRules::Resolve (TyTy::TyWithLocation (a),
+ TyTy::TyWithLocation (b), locus,
+ commit_flag, false /* emit_errors */);
+ if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+ }
+
+ auto unified_return
+ = UnifyRules::Resolve (TyTy::TyWithLocation (
+ ltype->get_return_type ()),
+ TyTy::TyWithLocation (type.get_return_type ()),
+ locus, commit_flag, false /* emit_errors */);
+ if (unified_return->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::FNDEF: {
+ TyTy::FnType &type = *static_cast<TyTy::FnType *> (rtype);
+ auto this_ret_type = ltype->get_return_type ();
+ auto other_ret_type = type.get_return_type ();
+
+ auto unified_result
+ = UnifyRules::Resolve (TyTy::TyWithLocation (this_ret_type),
+ TyTy::TyWithLocation (other_ret_type), locus,
+ commit_flag, false /*emit_errors*/);
+ if (unified_result->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ if (ltype->num_params () != type.num_params ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ for (size_t i = 0; i < ltype->num_params (); i++)
+ {
+ auto this_param = ltype->param_at (i);
+ auto other_param = type.param_at (i).second;
+
+ auto unified_param
+ = UnifyRules::Resolve (TyTy::TyWithLocation (this_param),
+ TyTy::TyWithLocation (other_param), locus,
+ commit_flag, false /* emit_errors */);
+ if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+ }
+
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::FLOAT:
+ case TyTy::ISIZE:
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::UINT:
+ case TyTy::USIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::TUPLE: {
+ TyTy::TupleType &type = *static_cast<TyTy::TupleType *> (rtype);
+ if (ltype->num_fields () != type.num_fields ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ std::vector<TyTy::TyVar> fields;
+ for (size_t i = 0; i < ltype->num_fields (); i++)
+ {
+ TyTy::BaseType *bo = ltype->get_field (i);
+ TyTy::BaseType *fo = type.get_field (i);
+
+ TyTy::BaseType *unified_ty
+ = UnifyRules::Resolve (TyTy::TyWithLocation (bo),
+ TyTy::TyWithLocation (fo), locus,
+ commit_flag, false /* emit_errors */);
+ if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
+ return new TyTy::ErrorType (0);
+
+ fields.push_back (TyTy::TyVar (unified_ty->get_ref ()));
+ }
+
+ return new TyTy::TupleType (type.get_ref (), type.get_ty_ref (),
+ type.get_ident ().locus, fields);
+ }
+ break;
+
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::FLOAT:
+ case TyTy::ISIZE:
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::UINT:
+ case TyTy::USIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::BOOL:
+ return rtype->clone ();
+
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::FLOAT:
+ case TyTy::ISIZE:
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::UINT:
+ case TyTy::USIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::CHAR:
+ return rtype->clone ();
+
+ case TyTy::INT:
+ case TyTy::FLOAT:
+ case TyTy::ISIZE:
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::UINT:
+ case TyTy::USIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL
+ || r->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::INT: {
+ TyTy::IntType &type = *static_cast<TyTy::IntType *> (rtype);
+ bool is_valid = ltype->get_int_kind () == type.get_int_kind ();
+ if (is_valid)
+ return new TyTy::IntType (type.get_ref (), type.get_ty_ref (),
+ type.get_int_kind ());
+ }
+ break;
+
+ case TyTy::FLOAT:
+ case TyTy::ISIZE:
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::UINT:
+ case TyTy::USIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL
+ || r->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::UINT: {
+ TyTy::UintType &type = *static_cast<TyTy::UintType *> (rtype);
+ bool is_valid = ltype->get_uint_kind () == type.get_uint_kind ();
+ if (is_valid)
+ return new TyTy::UintType (type.get_ref (), type.get_ty_ref (),
+ type.get_uint_kind ());
+ }
+ break;
+
+ case TyTy::FLOAT:
+ case TyTy::ISIZE:
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::USIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL
+ || r->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::FLOAT: {
+ TyTy::FloatType &type = *static_cast<TyTy::FloatType *> (rtype);
+ bool is_valid = ltype->get_float_kind () == type.get_float_kind ();
+ if (is_valid)
+ return new TyTy::FloatType (type.get_ref (), type.get_ty_ref (),
+ type.get_float_kind ());
+ }
+ break;
+
+ case TyTy::ISIZE:
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::USIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::ISIZE:
+ return rtype->clone ();
+
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::FLOAT:
+ case TyTy::USIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::USIZE:
+ return rtype->clone ();
+
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::FLOAT:
+ case TyTy::ISIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_never (TyTy::NeverType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::NEVER:
+ return rtype->clone ();
+
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::SLICE:
+ case TyTy::PARAM:
+ case TyTy::POINTER:
+ case TyTy::STR:
+ case TyTy::ADT:
+ case TyTy::REF:
+ case TyTy::ARRAY:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::FLOAT:
+ case TyTy::USIZE:
+ case TyTy::ISIZE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_placeholder (TyTy::PlaceholderType *ltype,
+ TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::PLACEHOLDER: {
+ TyTy::PlaceholderType &type
+ = *static_cast<TyTy::PlaceholderType *> (rtype);
+ bool symbol_match
+ = ltype->get_symbol ().compare (type.get_symbol ()) == 0;
+ if (symbol_match)
+ {
+ return type.clone ();
+ }
+ }
+ break;
+
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::SLICE:
+ case TyTy::PARAM:
+ case TyTy::POINTER:
+ case TyTy::STR:
+ case TyTy::ADT:
+ case TyTy::REF:
+ case TyTy::ARRAY:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::FLOAT:
+ case TyTy::USIZE:
+ case TyTy::ISIZE:
+ case TyTy::NEVER:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_projection (TyTy::ProjectionType *ltype,
+ TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ // FIXME
+ case TyTy::PROJECTION:
+ gcc_unreachable ();
+ break;
+
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::SLICE:
+ case TyTy::PARAM:
+ case TyTy::POINTER:
+ case TyTy::STR:
+ case TyTy::ADT:
+ case TyTy::REF:
+ case TyTy::ARRAY:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::FLOAT:
+ case TyTy::USIZE:
+ case TyTy::ISIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::DYNAMIC: {
+ TyTy::DynamicObjectType &type
+ = *static_cast<TyTy::DynamicObjectType *> (rtype);
+ if (ltype->num_specified_bounds () != type.num_specified_bounds ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ if (!ltype->bounds_compatible (type, locus, true))
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::CLOSURE:
+ case TyTy::SLICE:
+ case TyTy::PARAM:
+ case TyTy::POINTER:
+ case TyTy::STR:
+ case TyTy::ADT:
+ case TyTy::REF:
+ case TyTy::ARRAY:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::FLOAT:
+ case TyTy::USIZE:
+ case TyTy::ISIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::CLOSURE: {
+ TyTy::ClosureType &type = *static_cast<TyTy::ClosureType *> (rtype);
+ if (ltype->get_def_id () != type.get_def_id ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ TyTy::BaseType *args_res
+ = UnifyRules::Resolve (TyTy::TyWithLocation (
+ <ype->get_parameters ()),
+ TyTy::TyWithLocation (&type.get_parameters ()),
+ locus, commit_flag, false /* emit_error */);
+ if (args_res->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ TyTy::BaseType *res = UnifyRules::Resolve (
+ TyTy::TyWithLocation (<ype->get_result_type ()),
+ TyTy::TyWithLocation (&type.get_result_type ()), locus, commit_flag,
+ false /* emit_error */);
+ if (res == nullptr || res->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::SLICE:
+ case TyTy::PARAM:
+ case TyTy::POINTER:
+ case TyTy::STR:
+ case TyTy::ADT:
+ case TyTy::REF:
+ case TyTy::ARRAY:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::FLOAT:
+ case TyTy::USIZE:
+ case TyTy::ISIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+} // namespace Resolver
+} // namespace Rust
new file mode 100644
@@ -0,0 +1,91 @@
+// Copyright (C) 2020-2022 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_UNIFY
+#define RUST_UNIFY
+
+#include "rust-tyty-util.h"
+#include "rust-hir-type-check.h"
+
+namespace Rust {
+namespace Resolver {
+
+class UnifyRules
+{
+public:
+ static TyTy::BaseType *Resolve (TyTy::TyWithLocation lhs,
+ TyTy::TyWithLocation rhs, Location locus,
+ bool commit_flag, bool emit_error);
+
+protected:
+ TyTy::BaseType *expect_inference_variable (TyTy::InferType *ltype,
+ TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_reference (TyTy::ReferenceType *ltype,
+ TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_pointer (TyTy::PointerType *ltype,
+ TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_never (TyTy::NeverType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_placeholder (TyTy::PlaceholderType *ltype,
+ TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_projection (TyTy::ProjectionType *ltype,
+ TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_dyn (TyTy::DynamicObjectType *ltype,
+ TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_closure (TyTy::ClosureType *ltype,
+ TyTy::BaseType *rtype);
+
+private:
+ UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
+ Location locus, bool commit_flag, bool emit_error);
+
+ void emit_type_mismatch () const;
+ void commit (TyTy::BaseType *resolved);
+ TyTy::BaseType *go ();
+
+ TyTy::BaseType *get_base ();
+ TyTy::BaseType *get_other ();
+
+ TyTy::TyWithLocation lhs;
+ TyTy::TyWithLocation rhs;
+ Location locus;
+ bool commit_flag;
+ bool emit_error;
+
+ Analysis::Mappings &mappings;
+ TypeCheckContext &context;
+};
+
+} // namespace Resolver
+} // namespace Rust
+
+#endif // RUST_UNIFY
similarity index 52%
rename from gcc/testsuite/rust/compile/never_type_err1.rs
rename to gcc/testsuite/rust/compile/never_type1.rs
@@ -1,8 +1,7 @@
fn test() {
let a;
- // FIXME: Unimplemented features
- a = if true { // { dg-error "expected .T.. got .!." }
+ a = if true {
return;
} else {
return;