aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2023-02-05 00:56:44 +0000
committerGitHub <noreply@github.com>2023-02-05 00:56:44 +0000
commit8f1fce4916520b7ee9a97d2bb4f25d25fd94a626 (patch)
treefb2b8f475720233153b06864ffd4d5fc72ed35df /gcc
parent47a9a9e949d7660ae7fc7cd4642f668bf438c970 (diff)
parent6d7a7b22882433d46bf4e4efe8c43343892c91eb (diff)
downloadgcc-8f1fce4916520b7ee9a97d2bb4f25d25fd94a626.zip
gcc-8f1fce4916520b7ee9a97d2bb4f25d25fd94a626.tar.gz
gcc-8f1fce4916520b7ee9a97d2bb4f25d25fd94a626.tar.bz2
Merge #1739
1739: Initial type bounds checking for all type checks r=philberty a=philberty This patchset is my branch for general improvements to the type-system and for improved type bounds checking in preparation for opaque types. Fixes #1773 #1786 Co-authored-by: Philip Herron <herron.philip@googlemail.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/Make-lang.in5
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc6
-rw-r--r--gcc/rust/typecheck/rust-coercion.cc6
-rw-r--r--gcc/rust/typecheck/rust-hir-path-probe.cc453
-rw-r--r--gcc/rust/typecheck/rust-hir-path-probe.h382
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-reference.h (renamed from gcc/rust/typecheck/rust-hir-trait-ref.h)6
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.cc42
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.h9
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.cc15
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-path.cc36
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h334
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.cc343
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.h286
-rw-r--r--gcc/rust/typecheck/rust-tyctx.cc190
-rw-r--r--gcc/rust/typecheck/rust-typecheck-context.cc569
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.cc26
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.h88
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.cc6
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h1406
-rw-r--r--gcc/rust/typecheck/rust-tyty-subst.cc1027
-rw-r--r--gcc/rust/typecheck/rust-tyty-subst.h317
-rw-r--r--gcc/rust/typecheck/rust-tyty-util.cc116
-rw-r--r--gcc/rust/typecheck/rust-tyty-util.h69
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc1793
-rw-r--r--gcc/rust/typecheck/rust-tyty.h1374
-rw-r--r--gcc/rust/typecheck/rust-unify.cc1651
-rw-r--r--gcc/rust/typecheck/rust-unify.h91
-rw-r--r--gcc/rust/util/rust-lang-item.h24
-rw-r--r--gcc/testsuite/rust/bounds1.rs19
-rw-r--r--gcc/testsuite/rust/compile/func3.rs1
-rw-r--r--gcc/testsuite/rust/compile/issue-1773.rs20
-rw-r--r--gcc/testsuite/rust/compile/issue-1786.rs23
-rw-r--r--gcc/testsuite/rust/compile/never_type1.rs (renamed from gcc/testsuite/rust/compile/never_type_err1.rs)3
-rw-r--r--gcc/testsuite/rust/compile/torture/intrinsics-4.rs63
-rw-r--r--gcc/testsuite/rust/compile/torture/intrinsics-5.rs66
-rw-r--r--gcc/testsuite/rust/execute/torture/atomic_load.rs59
-rw-r--r--gcc/testsuite/rust/execute/torture/atomic_store.rs59
-rw-r--r--gcc/testsuite/rust/execute/torture/issue-1720-2.rs30
38 files changed, 6595 insertions, 4418 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 1aebf79..6038c84 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -115,8 +115,10 @@ GRS_OBJS = \
rust/rust-pub-restricted-visitor.o \
rust/rust-privacy-reporter.o \
rust/rust-tyty.o \
+ rust/rust-tyty-util.o \
rust/rust-tyty-call.o \
- rust/rust-tyctx.o \
+ rust/rust-tyty-subst.o \
+ rust/rust-typecheck-context.o \
rust/rust-tyty-bounds.o \
rust/rust-hir-type-check-util.o \
rust/rust-hir-trait-resolve.o \
@@ -132,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 \
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 76d70cc..1890b57 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -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);
diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc
index a361856..6236078 100644
--- a/gcc/rust/typecheck/rust-coercion.cc
+++ b/gcc/rust/typecheck/rust-coercion.cc
@@ -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};
}
}
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.cc b/gcc/rust/typecheck/rust-hir-path-probe.cc
index cb3270d..be89ceb 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.cc
+++ b/gcc/rust/typecheck/rust-hir-path-probe.cc
@@ -18,10 +18,277 @@
#include "rust-hir-path-probe.h"
#include "rust-hir-type-check-item.h"
+#include "rust-hir-trait-resolve.h"
namespace Rust {
namespace Resolver {
+// PathProbeCandidate
+
+PathProbeCandidate::Candidate::Candidate (EnumItemCandidate enum_field)
+ : enum_field (enum_field)
+{}
+
+PathProbeCandidate::Candidate::Candidate (ImplItemCandidate impl) : impl (impl)
+{}
+
+PathProbeCandidate::Candidate::Candidate (TraitItemCandidate trait)
+ : trait (trait)
+{}
+
+PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty,
+ Location locus,
+ EnumItemCandidate enum_field)
+ : type (type), ty (ty), locus (locus), item (enum_field)
+{}
+
+PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty,
+ Location locus, ImplItemCandidate impl)
+ : type (type), ty (ty), locus (locus), item (impl)
+{}
+
+PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty,
+ Location locus,
+ TraitItemCandidate trait)
+ : type (type), ty (ty), locus (locus), item (trait)
+{}
+
+std::string
+PathProbeCandidate::as_string () const
+{
+ return "PathProbe candidate TODO - as_string";
+}
+
+bool
+PathProbeCandidate::is_enum_candidate () const
+{
+ return type == ENUM_VARIANT;
+}
+
+bool
+PathProbeCandidate::is_impl_candidate () const
+{
+ return type == IMPL_CONST || type == IMPL_TYPE_ALIAS || type == IMPL_FUNC;
+}
+
+bool
+PathProbeCandidate::is_trait_candidate () const
+{
+ return type == TRAIT_ITEM_CONST || type == TRAIT_TYPE_ALIAS
+ || type == TRAIT_FUNC;
+}
+
+bool
+PathProbeCandidate::is_full_trait_item_candidate () const
+{
+ return is_trait_candidate () && item.trait.impl == nullptr;
+}
+
+PathProbeCandidate
+PathProbeCandidate::get_error ()
+{
+ return PathProbeCandidate (ERROR, nullptr, Location (),
+ ImplItemCandidate{nullptr, nullptr});
+}
+
+bool
+PathProbeCandidate::is_error () const
+{
+ return type == ERROR;
+}
+
+DefId
+PathProbeCandidate::get_defid () const
+{
+ switch (type)
+ {
+ case ENUM_VARIANT:
+ return item.enum_field.variant->get_defid ();
+ break;
+
+ case IMPL_CONST:
+ case IMPL_TYPE_ALIAS:
+ case IMPL_FUNC:
+ return item.impl.impl_item->get_impl_mappings ().get_defid ();
+ break;
+
+ case TRAIT_ITEM_CONST:
+ case TRAIT_TYPE_ALIAS:
+ case TRAIT_FUNC:
+ return item.trait.item_ref->get_mappings ().get_defid ();
+ break;
+
+ case ERROR:
+ default:
+ return UNKNOWN_DEFID;
+ }
+
+ return UNKNOWN_DEFID;
+}
+
+bool
+PathProbeCandidate::operator< (const PathProbeCandidate &c) const
+{
+ return get_defid () < c.get_defid ();
+}
+
+// PathProbeType
+
+PathProbeType::PathProbeType (const TyTy::BaseType *receiver,
+ const HIR::PathIdentSegment &query,
+ DefId specific_trait_id)
+ : TypeCheckBase (), receiver (receiver), search (query),
+ current_impl (nullptr), specific_trait_id (specific_trait_id)
+{}
+
+std::set<PathProbeCandidate>
+PathProbeType::Probe (const TyTy::BaseType *receiver,
+ const HIR::PathIdentSegment &segment_name,
+ bool probe_impls, bool probe_bounds,
+ bool ignore_mandatory_trait_items,
+ DefId specific_trait_id)
+{
+ PathProbeType probe (receiver, segment_name, specific_trait_id);
+ if (probe_impls)
+ {
+ if (receiver->get_kind () == TyTy::TypeKind::ADT)
+ {
+ const TyTy::ADTType *adt
+ = static_cast<const TyTy::ADTType *> (receiver);
+ if (adt->is_enum ())
+ probe.process_enum_item_for_candiates (adt);
+ }
+
+ probe.process_impl_items_for_candidates ();
+ }
+
+ if (!probe_bounds)
+ return probe.candidates;
+
+ if (!probe.is_reciever_generic ())
+ {
+ std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> probed_bounds
+ = TypeBoundsProbe::Probe (receiver);
+ for (auto &candidate : probed_bounds)
+ {
+ const TraitReference *trait_ref = candidate.first;
+ if (specific_trait_id != UNKNOWN_DEFID)
+ {
+ if (trait_ref->get_mappings ().get_defid () != specific_trait_id)
+ continue;
+ }
+
+ HIR::ImplBlock *impl = candidate.second;
+ probe.process_associated_trait_for_candidates (
+ trait_ref, impl, ignore_mandatory_trait_items);
+ }
+ }
+
+ for (const TyTy::TypeBoundPredicate &predicate :
+ receiver->get_specified_bounds ())
+ {
+ const TraitReference *trait_ref = predicate.get ();
+ if (specific_trait_id != UNKNOWN_DEFID)
+ {
+ if (trait_ref->get_mappings ().get_defid () != specific_trait_id)
+ continue;
+ }
+
+ probe.process_predicate_for_candidates (predicate,
+ ignore_mandatory_trait_items);
+ }
+
+ return probe.candidates;
+}
+
+void
+PathProbeType::visit (HIR::TypeAlias &alias)
+{
+ Identifier name = alias.get_new_type_name ();
+ if (search.as_string ().compare (name) == 0)
+ {
+ HirId tyid = alias.get_mappings ().get_hirid ();
+ TyTy::BaseType *ty = nullptr;
+ bool ok = query_type (tyid, &ty);
+ rust_assert (ok);
+
+ PathProbeCandidate::ImplItemCandidate impl_item_candidate{&alias,
+ current_impl};
+ PathProbeCandidate candidate{
+ PathProbeCandidate::CandidateType::IMPL_TYPE_ALIAS, ty,
+ alias.get_locus (), impl_item_candidate};
+ candidates.insert (std::move (candidate));
+ }
+}
+
+void
+PathProbeType::visit (HIR::ConstantItem &constant)
+{
+ Identifier name = constant.get_identifier ();
+ if (search.as_string ().compare (name) == 0)
+ {
+ HirId tyid = constant.get_mappings ().get_hirid ();
+ TyTy::BaseType *ty = nullptr;
+ bool ok = query_type (tyid, &ty);
+ rust_assert (ok);
+
+ PathProbeCandidate::ImplItemCandidate impl_item_candidate{&constant,
+ current_impl};
+ PathProbeCandidate candidate{
+ PathProbeCandidate::CandidateType::IMPL_CONST, ty,
+ constant.get_locus (), impl_item_candidate};
+ candidates.insert (std::move (candidate));
+ }
+}
+
+void
+PathProbeType::visit (HIR::Function &function)
+{
+ Identifier name = function.get_function_name ();
+ if (search.as_string ().compare (name) == 0)
+ {
+ HirId tyid = function.get_mappings ().get_hirid ();
+ TyTy::BaseType *ty = nullptr;
+ bool ok = query_type (tyid, &ty);
+ rust_assert (ok);
+
+ PathProbeCandidate::ImplItemCandidate impl_item_candidate{&function,
+ current_impl};
+ PathProbeCandidate candidate{PathProbeCandidate::CandidateType::IMPL_FUNC,
+ ty, function.get_locus (),
+ impl_item_candidate};
+ candidates.insert (std::move (candidate));
+ }
+}
+
+void
+PathProbeType::process_enum_item_for_candiates (const TyTy::ADTType *adt)
+{
+ if (specific_trait_id != UNKNOWN_DEFID)
+ return;
+
+ TyTy::VariantDef *v;
+ if (!adt->lookup_variant (search.as_string (), &v))
+ return;
+
+ PathProbeCandidate::EnumItemCandidate enum_item_candidate{adt, v};
+ PathProbeCandidate candidate{PathProbeCandidate::CandidateType::ENUM_VARIANT,
+ receiver->clone (),
+ mappings->lookup_location (adt->get_ty_ref ()),
+ enum_item_candidate};
+ candidates.insert (std::move (candidate));
+}
+
+void
+PathProbeType::process_impl_items_for_candidates ()
+{
+ mappings->iterate_impl_items (
+ [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool {
+ process_impl_item_candidate (id, item, impl);
+ return true;
+ });
+}
+
void
PathProbeType::process_impl_item_candidate (HirId id, HIR::ImplItem *item,
HIR::ImplBlock *impl)
@@ -42,5 +309,191 @@ PathProbeType::process_impl_item_candidate (HirId id, HIR::ImplItem *item,
item->accept_vis (*this);
}
+void
+PathProbeType::process_associated_trait_for_candidates (
+ const TraitReference *trait_ref, HIR::ImplBlock *impl,
+ bool ignore_mandatory_trait_items)
+{
+ const TraitItemReference *trait_item_ref = nullptr;
+ if (!trait_ref->lookup_trait_item (search.as_string (), &trait_item_ref))
+ return;
+
+ bool trait_item_needs_implementation = !trait_item_ref->is_optional ();
+ if (ignore_mandatory_trait_items && trait_item_needs_implementation)
+ return;
+
+ PathProbeCandidate::CandidateType candidate_type;
+ switch (trait_item_ref->get_trait_item_type ())
+ {
+ case TraitItemReference::TraitItemType::FN:
+ candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
+ break;
+ case TraitItemReference::TraitItemType::CONST:
+ candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
+ break;
+ case TraitItemReference::TraitItemType::TYPE:
+ candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
+ break;
+
+ case TraitItemReference::TraitItemType::ERROR:
+ default:
+ gcc_unreachable ();
+ break;
+ }
+
+ TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty ();
+
+ // we can substitute the Self with the receiver here
+ if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF)
+ {
+ TyTy::FnType *fn = static_cast<TyTy::FnType *> (trait_item_tyty);
+ TyTy::SubstitutionParamMapping *param = nullptr;
+ for (auto &param_mapping : fn->get_substs ())
+ {
+ const HIR::TypeParam &type_param = param_mapping.get_generic_param ();
+ if (type_param.get_type_representation ().compare ("Self") == 0)
+ {
+ param = &param_mapping;
+ break;
+ }
+ }
+ rust_assert (param != nullptr);
+
+ std::vector<TyTy::SubstitutionArg> mappings;
+ mappings.push_back (TyTy::SubstitutionArg (param, receiver->clone ()));
+
+ Location locus; // FIXME
+ TyTy::SubstitutionArgumentMappings args (std::move (mappings), {}, locus);
+ trait_item_tyty = SubstMapperInternal::Resolve (trait_item_tyty, args);
+ }
+
+ PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
+ trait_item_ref,
+ impl};
+
+ PathProbeCandidate candidate{candidate_type, trait_item_tyty,
+ trait_item_ref->get_locus (),
+ trait_item_candidate};
+ candidates.insert (std::move (candidate));
+}
+
+void
+PathProbeType::process_predicate_for_candidates (
+ const TyTy::TypeBoundPredicate &predicate, bool ignore_mandatory_trait_items)
+{
+ const TraitReference *trait_ref = predicate.get ();
+
+ TyTy::TypeBoundPredicateItem item
+ = predicate.lookup_associated_item (search.as_string ());
+ if (item.is_error ())
+ return;
+
+ if (ignore_mandatory_trait_items && item.needs_implementation ())
+ return;
+
+ const TraitItemReference *trait_item_ref = item.get_raw_item ();
+ PathProbeCandidate::CandidateType candidate_type;
+ switch (trait_item_ref->get_trait_item_type ())
+ {
+ case TraitItemReference::TraitItemType::FN:
+ candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
+ break;
+ case TraitItemReference::TraitItemType::CONST:
+ candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
+ break;
+ case TraitItemReference::TraitItemType::TYPE:
+ candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
+ break;
+
+ case TraitItemReference::TraitItemType::ERROR:
+ default:
+ gcc_unreachable ();
+ break;
+ }
+
+ TyTy::BaseType *trait_item_tyty = item.get_tyty_for_receiver (receiver);
+ PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
+ trait_item_ref,
+ nullptr};
+ PathProbeCandidate candidate{candidate_type, trait_item_tyty,
+ trait_item_ref->get_locus (),
+ trait_item_candidate};
+ candidates.insert (std::move (candidate));
+}
+
+std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>>
+PathProbeType::union_bounds (
+ const std::vector<std::pair</*const*/ TraitReference *, HIR::ImplBlock *>> a,
+ const std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> b)
+ const
+{
+ std::map<DefId, std::pair<const TraitReference *, HIR::ImplBlock *>> mapper;
+ for (auto &ref : a)
+ {
+ mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
+ }
+ for (auto &ref : b)
+ {
+ mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
+ }
+
+ std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> union_set;
+ for (auto it = mapper.begin (); it != mapper.end (); it++)
+ {
+ union_set.push_back ({it->second.first, it->second.second});
+ }
+ return union_set;
+}
+
+bool
+PathProbeType::is_reciever_generic () const
+{
+ const TyTy::BaseType *root = receiver->get_root ();
+ bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM;
+ bool receiver_is_dyn = root->get_kind () == TyTy::TypeKind::DYNAMIC;
+ return receiver_is_type_param || receiver_is_dyn;
+}
+
+// PathProbImplTrait
+
+PathProbeImplTrait::PathProbeImplTrait (const TyTy::BaseType *receiver,
+ const HIR::PathIdentSegment &query,
+ const TraitReference *trait_reference)
+ : PathProbeType (receiver, query, UNKNOWN_DEFID),
+ trait_reference (trait_reference)
+{}
+
+std::set<PathProbeCandidate>
+PathProbeImplTrait::Probe (const TyTy::BaseType *receiver,
+ const HIR::PathIdentSegment &segment_name,
+ const TraitReference *trait_reference)
+{
+ PathProbeImplTrait probe (receiver, segment_name, trait_reference);
+ // iterate all impls for this trait and receiver
+ // then search for possible candidates using base class behaviours
+ probe.process_trait_impl_items_for_candidates ();
+ return probe.candidates;
+}
+
+void
+PathProbeImplTrait::process_trait_impl_items_for_candidates ()
+{
+ mappings->iterate_impl_items (
+ [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool {
+ // just need to check if this is an impl block for this trait the next
+ // function checks the receiver
+ if (!impl->has_trait_ref ())
+ return true;
+
+ TraitReference *resolved
+ = TraitResolver::Lookup (*(impl->get_trait_ref ().get ()));
+ if (!trait_reference->is_equal (*resolved))
+ return true;
+
+ process_impl_item_candidate (id, item, impl);
+ return true;
+ });
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h
index ac7d4f5..0bb3b99 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe.h
@@ -73,89 +73,37 @@ struct PathProbeCandidate
ImplItemCandidate impl;
TraitItemCandidate trait;
- Candidate (EnumItemCandidate enum_field) : enum_field (enum_field) {}
- Candidate (ImplItemCandidate impl) : impl (impl) {}
- Candidate (TraitItemCandidate trait) : trait (trait) {}
+ Candidate (EnumItemCandidate enum_field);
+ Candidate (ImplItemCandidate impl);
+ Candidate (TraitItemCandidate trait);
} item;
PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus,
- EnumItemCandidate enum_field)
- : type (type), ty (ty), locus (locus), item (enum_field)
- {}
+ EnumItemCandidate enum_field);
PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus,
- ImplItemCandidate impl)
- : type (type), ty (ty), locus (locus), item (impl)
- {}
+ ImplItemCandidate impl);
PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus,
- TraitItemCandidate trait)
- : type (type), ty (ty), locus (locus), item (trait)
- {}
+ TraitItemCandidate trait);
- std::string as_string () const
- {
- return "PathProbe candidate TODO - as_string";
- }
+ std::string as_string () const;
- bool is_enum_candidate () const { return type == ENUM_VARIANT; }
+ bool is_enum_candidate () const;
- bool is_impl_candidate () const
- {
- return type == IMPL_CONST || type == IMPL_TYPE_ALIAS || type == IMPL_FUNC;
- }
+ bool is_impl_candidate () const;
- bool is_trait_candidate () const
- {
- return type == TRAIT_ITEM_CONST || type == TRAIT_TYPE_ALIAS
- || type == TRAIT_FUNC;
- }
+ bool is_trait_candidate () const;
- bool is_full_trait_item_candidate () const
- {
- return is_trait_candidate () && item.trait.impl == nullptr;
- }
+ bool is_full_trait_item_candidate () const;
- static PathProbeCandidate get_error ()
- {
- return PathProbeCandidate (ERROR, nullptr, Location (),
- ImplItemCandidate{nullptr, nullptr});
- }
+ static PathProbeCandidate get_error ();
- bool is_error () const { return type == ERROR; }
+ bool is_error () const;
- DefId get_defid () const
- {
- switch (type)
- {
- case ENUM_VARIANT:
- return item.enum_field.variant->get_defid ();
- break;
-
- case IMPL_CONST:
- case IMPL_TYPE_ALIAS:
- case IMPL_FUNC:
- return item.impl.impl_item->get_impl_mappings ().get_defid ();
- break;
-
- case TRAIT_ITEM_CONST:
- case TRAIT_TYPE_ALIAS:
- case TRAIT_FUNC:
- return item.trait.item_ref->get_mappings ().get_defid ();
- break;
-
- case ERROR:
- default:
- return UNKNOWN_DEFID;
- }
-
- return UNKNOWN_DEFID;
- }
+ DefId get_defid () const;
- bool operator< (const PathProbeCandidate &c) const
- {
- return get_defid () < c.get_defid ();
- }
+ bool operator< (const PathProbeCandidate &c) const;
};
class PathProbeType : public TypeCheckBase, public HIR::HIRImplVisitor
@@ -165,144 +113,16 @@ public:
Probe (const TyTy::BaseType *receiver,
const HIR::PathIdentSegment &segment_name, bool probe_impls,
bool probe_bounds, bool ignore_mandatory_trait_items,
- DefId specific_trait_id = UNKNOWN_DEFID)
- {
- PathProbeType probe (receiver, segment_name, specific_trait_id);
- if (probe_impls)
- {
- if (receiver->get_kind () == TyTy::TypeKind::ADT)
- {
- const TyTy::ADTType *adt
- = static_cast<const TyTy::ADTType *> (receiver);
- if (adt->is_enum ())
- probe.process_enum_item_for_candiates (adt);
- }
-
- probe.process_impl_items_for_candidates ();
- }
-
- if (!probe_bounds)
- return probe.candidates;
-
- if (!probe.is_reciever_generic ())
- {
- std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> probed_bounds
- = TypeBoundsProbe::Probe (receiver);
- for (auto &candidate : probed_bounds)
- {
- const TraitReference *trait_ref = candidate.first;
- if (specific_trait_id != UNKNOWN_DEFID)
- {
- if (trait_ref->get_mappings ().get_defid ()
- != specific_trait_id)
- continue;
- }
-
- HIR::ImplBlock *impl = candidate.second;
- probe.process_associated_trait_for_candidates (
- trait_ref, impl, ignore_mandatory_trait_items);
- }
- }
-
- for (const TyTy::TypeBoundPredicate &predicate :
- receiver->get_specified_bounds ())
- {
- const TraitReference *trait_ref = predicate.get ();
- if (specific_trait_id != UNKNOWN_DEFID)
- {
- if (trait_ref->get_mappings ().get_defid () != specific_trait_id)
- continue;
- }
-
- probe.process_predicate_for_candidates (predicate,
- ignore_mandatory_trait_items);
- }
-
- return probe.candidates;
- }
-
- void visit (HIR::TypeAlias &alias) override
- {
- Identifier name = alias.get_new_type_name ();
- if (search.as_string ().compare (name) == 0)
- {
- HirId tyid = alias.get_mappings ().get_hirid ();
- TyTy::BaseType *ty = nullptr;
- bool ok = query_type (tyid, &ty);
- rust_assert (ok);
-
- PathProbeCandidate::ImplItemCandidate impl_item_candidate{&alias,
- current_impl};
- PathProbeCandidate candidate{
- PathProbeCandidate::CandidateType::IMPL_TYPE_ALIAS, ty,
- alias.get_locus (), impl_item_candidate};
- candidates.insert (std::move (candidate));
- }
- }
-
- void visit (HIR::ConstantItem &constant) override
- {
- Identifier name = constant.get_identifier ();
- if (search.as_string ().compare (name) == 0)
- {
- HirId tyid = constant.get_mappings ().get_hirid ();
- TyTy::BaseType *ty = nullptr;
- bool ok = query_type (tyid, &ty);
- rust_assert (ok);
-
- PathProbeCandidate::ImplItemCandidate impl_item_candidate{&constant,
- current_impl};
- PathProbeCandidate candidate{
- PathProbeCandidate::CandidateType::IMPL_CONST, ty,
- constant.get_locus (), impl_item_candidate};
- candidates.insert (std::move (candidate));
- }
- }
+ DefId specific_trait_id = UNKNOWN_DEFID);
- void visit (HIR::Function &function) override
- {
- Identifier name = function.get_function_name ();
- if (search.as_string ().compare (name) == 0)
- {
- HirId tyid = function.get_mappings ().get_hirid ();
- TyTy::BaseType *ty = nullptr;
- bool ok = query_type (tyid, &ty);
- rust_assert (ok);
-
- PathProbeCandidate::ImplItemCandidate impl_item_candidate{&function,
- current_impl};
- PathProbeCandidate candidate{
- PathProbeCandidate::CandidateType::IMPL_FUNC, ty,
- function.get_locus (), impl_item_candidate};
- candidates.insert (std::move (candidate));
- }
- }
+ void visit (HIR::TypeAlias &alias) override;
+ void visit (HIR::ConstantItem &constant) override;
+ void visit (HIR::Function &function) override;
protected:
- void process_enum_item_for_candiates (const TyTy::ADTType *adt)
- {
- if (specific_trait_id != UNKNOWN_DEFID)
- return;
-
- TyTy::VariantDef *v;
- if (!adt->lookup_variant (search.as_string (), &v))
- return;
-
- PathProbeCandidate::EnumItemCandidate enum_item_candidate{adt, v};
- PathProbeCandidate candidate{
- PathProbeCandidate::CandidateType::ENUM_VARIANT, receiver->clone (),
- mappings->lookup_location (adt->get_ty_ref ()), enum_item_candidate};
- candidates.insert (std::move (candidate));
- }
+ void process_enum_item_for_candiates (const TyTy::ADTType *adt);
- void process_impl_items_for_candidates ()
- {
- mappings->iterate_impl_items ([&] (HirId id, HIR::ImplItem *item,
- HIR::ImplBlock *impl) mutable -> bool {
- process_impl_item_candidate (id, item, impl);
- return true;
- });
- }
+ void process_impl_items_for_candidates ();
void process_impl_item_candidate (HirId id, HIR::ImplItem *item,
HIR::ImplBlock *impl);
@@ -310,156 +130,24 @@ protected:
void
process_associated_trait_for_candidates (const TraitReference *trait_ref,
HIR::ImplBlock *impl,
- bool ignore_mandatory_trait_items)
- {
- const TraitItemReference *trait_item_ref = nullptr;
- if (!trait_ref->lookup_trait_item (search.as_string (), &trait_item_ref))
- return;
-
- bool trait_item_needs_implementation = !trait_item_ref->is_optional ();
- if (ignore_mandatory_trait_items && trait_item_needs_implementation)
- return;
-
- PathProbeCandidate::CandidateType candidate_type;
- switch (trait_item_ref->get_trait_item_type ())
- {
- case TraitItemReference::TraitItemType::FN:
- candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
- break;
- case TraitItemReference::TraitItemType::CONST:
- candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
- break;
- case TraitItemReference::TraitItemType::TYPE:
- candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
- break;
-
- case TraitItemReference::TraitItemType::ERROR:
- default:
- gcc_unreachable ();
- break;
- }
-
- TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty ();
-
- // we can substitute the Self with the receiver here
- if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF)
- {
- TyTy::FnType *fn = static_cast<TyTy::FnType *> (trait_item_tyty);
- TyTy::SubstitutionParamMapping *param = nullptr;
- for (auto &param_mapping : fn->get_substs ())
- {
- const HIR::TypeParam &type_param
- = param_mapping.get_generic_param ();
- if (type_param.get_type_representation ().compare ("Self") == 0)
- {
- param = &param_mapping;
- break;
- }
- }
- rust_assert (param != nullptr);
-
- std::vector<TyTy::SubstitutionArg> mappings;
- mappings.push_back (TyTy::SubstitutionArg (param, receiver->clone ()));
-
- Location locus; // FIXME
- TyTy::SubstitutionArgumentMappings args (std::move (mappings), {},
- locus);
- trait_item_tyty = SubstMapperInternal::Resolve (trait_item_tyty, args);
- }
-
- PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
- trait_item_ref,
- impl};
-
- PathProbeCandidate candidate{candidate_type, trait_item_tyty,
- trait_item_ref->get_locus (),
- trait_item_candidate};
- candidates.insert (std::move (candidate));
- }
+ bool ignore_mandatory_trait_items);
void
process_predicate_for_candidates (const TyTy::TypeBoundPredicate &predicate,
- bool ignore_mandatory_trait_items)
- {
- const TraitReference *trait_ref = predicate.get ();
-
- TyTy::TypeBoundPredicateItem item
- = predicate.lookup_associated_item (search.as_string ());
- if (item.is_error ())
- return;
-
- if (ignore_mandatory_trait_items && item.needs_implementation ())
- return;
-
- const TraitItemReference *trait_item_ref = item.get_raw_item ();
- PathProbeCandidate::CandidateType candidate_type;
- switch (trait_item_ref->get_trait_item_type ())
- {
- case TraitItemReference::TraitItemType::FN:
- candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
- break;
- case TraitItemReference::TraitItemType::CONST:
- candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
- break;
- case TraitItemReference::TraitItemType::TYPE:
- candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
- break;
-
- case TraitItemReference::TraitItemType::ERROR:
- default:
- gcc_unreachable ();
- break;
- }
-
- TyTy::BaseType *trait_item_tyty = item.get_tyty_for_receiver (receiver);
- PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
- trait_item_ref,
- nullptr};
- PathProbeCandidate candidate{candidate_type, trait_item_tyty,
- trait_item_ref->get_locus (),
- trait_item_candidate};
- candidates.insert (std::move (candidate));
- }
+ bool ignore_mandatory_trait_items);
protected:
PathProbeType (const TyTy::BaseType *receiver,
- const HIR::PathIdentSegment &query, DefId specific_trait_id)
- : TypeCheckBase (), receiver (receiver), search (query),
- current_impl (nullptr), specific_trait_id (specific_trait_id)
- {}
+ const HIR::PathIdentSegment &query, DefId specific_trait_id);
std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>>
union_bounds (
const std::vector<std::pair</*const*/ TraitReference *, HIR::ImplBlock *>>
a,
const std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> b)
- const
- {
- std::map<DefId, std::pair<const TraitReference *, HIR::ImplBlock *>> mapper;
- for (auto &ref : a)
- {
- mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
- }
- for (auto &ref : b)
- {
- mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
- }
-
- std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> union_set;
- for (auto it = mapper.begin (); it != mapper.end (); it++)
- {
- union_set.push_back ({it->second.first, it->second.second});
- }
- return union_set;
- }
+ const;
- bool is_reciever_generic () const
- {
- const TyTy::BaseType *root = receiver->get_root ();
- bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM;
- bool receiver_is_dyn = root->get_kind () == TyTy::TypeKind::DYNAMIC;
- return receiver_is_type_param || receiver_is_dyn;
- }
+ bool is_reciever_generic () const;
const TyTy::BaseType *receiver;
const HIR::PathIdentSegment &search;
@@ -489,24 +177,14 @@ public:
static std::set<PathProbeCandidate>
Probe (const TyTy::BaseType *receiver,
const HIR::PathIdentSegment &segment_name,
- const TraitReference *trait_reference)
- {
- PathProbeImplTrait probe (receiver, segment_name, trait_reference);
- // iterate all impls for this trait and receiver
- // then search for possible candidates using base class behaviours
- probe.process_trait_impl_items_for_candidates ();
- return probe.candidates;
- }
+ const TraitReference *trait_reference);
private:
- void process_trait_impl_items_for_candidates ();
-
PathProbeImplTrait (const TyTy::BaseType *receiver,
const HIR::PathIdentSegment &query,
- const TraitReference *trait_reference)
- : PathProbeType (receiver, query, UNKNOWN_DEFID),
- trait_reference (trait_reference)
- {}
+ const TraitReference *trait_reference);
+
+ void process_trait_impl_items_for_candidates ();
const TraitReference *trait_reference;
};
diff --git a/gcc/rust/typecheck/rust-hir-trait-ref.h b/gcc/rust/typecheck/rust-hir-trait-reference.h
index d0814f6..aec1dd5 100644
--- a/gcc/rust/typecheck/rust-hir-trait-ref.h
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.h
@@ -496,9 +496,11 @@ public:
HIR::ImplBlock *get_impl_block () { return impl; }
TyTy::BaseType *get_self () { return self; }
+ const TyTy::BaseType *get_self () const { return self; }
- void setup_associated_types (const TyTy::BaseType *self,
- const TyTy::TypeBoundPredicate &bound);
+ TyTy::BaseType *
+ setup_associated_types (const TyTy::BaseType *self,
+ const TyTy::TypeBoundPredicate &bound);
void reset_associated_types ();
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index d968c20..a7e0735 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -22,6 +22,16 @@
namespace Rust {
namespace Resolver {
+TraitItemReference
+ResolveTraitItemToRef::Resolve (
+ HIR::TraitItem &item, TyTy::BaseType *self,
+ std::vector<TyTy::SubstitutionParamMapping> substitutions)
+{
+ ResolveTraitItemToRef resolver (self, std::move (substitutions));
+ item.accept_vis (resolver);
+ return std::move (resolver.resolved);
+}
+
void
ResolveTraitItemToRef::visit (HIR::TraitItemType &type)
{
@@ -367,13 +377,10 @@ TraitItemReference::associated_type_reset () const
placeholder->clear_associated_type ();
}
-void
+TyTy::BaseType *
AssociatedImplTrait::setup_associated_types (
const TyTy::BaseType *self, const TyTy::TypeBoundPredicate &bound)
{
- if (!bound.contains_associated_types ())
- return;
-
// compute the constrained impl block generic arguments based on self and the
// higher ranked trait bound
TyTy::BaseType *receiver = self->clone ();
@@ -476,6 +483,7 @@ AssociatedImplTrait::setup_associated_types (
TyTy::TyWithLocation (receiver), TyTy::TyWithLocation (impl_self_infer),
impl_predicate.get_locus ());
rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
+ TyTy::BaseType *self_result = result;
// unify the bounds arguments
std::vector<TyTy::BaseType *> hrtb_bound_arguments;
@@ -490,7 +498,7 @@ AssociatedImplTrait::setup_associated_types (
}
if (impl_trait_predicate_args.size () != hrtb_bound_arguments.size ())
- return;
+ return self_result;
for (size_t i = 0; i < impl_trait_predicate_args.size (); i++)
{
@@ -544,6 +552,8 @@ AssociatedImplTrait::setup_associated_types (
resolved_trait_item->associated_type_set (substituted);
});
iter.go ();
+
+ return self_result;
}
void
@@ -594,27 +604,5 @@ TraitItemReference::is_object_safe () const
return false;
}
-// rust-hir-path-probe.h
-
-void
-PathProbeImplTrait::process_trait_impl_items_for_candidates ()
-{
- mappings->iterate_impl_items (
- [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool {
- // just need to check if this is an impl block for this trait the next
- // function checks the receiver
- if (!impl->has_trait_ref ())
- return true;
-
- TraitReference *resolved
- = TraitResolver::Lookup (*(impl->get_trait_ref ().get ()));
- if (!trait_reference->is_equal (*resolved))
- return true;
-
- process_impl_item_candidate (id, item, impl);
- return true;
- });
-}
-
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.h b/gcc/rust/typecheck/rust-hir-trait-resolve.h
index 468f429..39365e0 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.h
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.h
@@ -19,9 +19,7 @@
#ifndef RUST_HIR_TRAIT_RESOLVE_H
#define RUST_HIR_TRAIT_RESOLVE_H
-#include "rust-hir-type-check-base.h"
#include "rust-hir-type-check-type.h"
-#include "rust-hir-trait-ref.h"
namespace Rust {
namespace Resolver {
@@ -32,12 +30,7 @@ class ResolveTraitItemToRef : public TypeCheckBase,
public:
static TraitItemReference
Resolve (HIR::TraitItem &item, TyTy::BaseType *self,
- std::vector<TyTy::SubstitutionParamMapping> substitutions)
- {
- ResolveTraitItemToRef resolver (self, std::move (substitutions));
- item.accept_vis (resolver);
- return std::move (resolver.resolved);
- }
+ std::vector<TyTy::SubstitutionParamMapping> substitutions);
void visit (HIR::TraitItemType &type) override;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index 8107ef5..6a63132 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc
@@ -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 *
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index 4e765ad..1625eda 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -379,16 +379,36 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
if (associated_impl_block != nullptr)
{
- // get the type of the parent Self
- HirId impl_ty_id
- = associated_impl_block->get_type ()->get_mappings ().get_hirid ();
+ // associated types
+ HirId impl_block_id
+ = associated_impl_block->get_mappings ().get_hirid ();
+
+ AssociatedImplTrait *associated = nullptr;
+ bool found_impl_trait
+ = context->lookup_associated_trait_impl (impl_block_id,
+ &associated);
TyTy::BaseType *impl_block_ty = nullptr;
- bool ok = query_type (impl_ty_id, &impl_block_ty);
- rust_assert (ok);
+ if (found_impl_trait)
+ {
+ TyTy::TypeBoundPredicate predicate (*associated->get_trait (),
+ seg.get_locus ());
+ impl_block_ty
+ = associated->setup_associated_types (prev_segment, predicate);
+ }
+ else
+ {
+ // get the type of the parent Self
+ HirId impl_ty_id = associated_impl_block->get_type ()
+ ->get_mappings ()
+ .get_hirid ();
- if (impl_block_ty->needs_generic_substitutions ())
- impl_block_ty
- = SubstMapper::InferSubst (impl_block_ty, seg.get_locus ());
+ bool ok = query_type (impl_ty_id, &impl_block_ty);
+ rust_assert (ok);
+
+ if (impl_block_ty->needs_generic_substitutions ())
+ impl_block_ty
+ = SubstMapper::InferSubst (impl_block_ty, seg.get_locus ());
+ }
prev_segment = unify_site (seg.get_mappings ().get_hirid (),
TyTy::TyWithLocation (prev_segment),
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index d785835..ee77497 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -22,7 +22,7 @@
#include "rust-hir-full-decls.h"
#include "rust-hir-map.h"
#include "rust-tyty.h"
-#include "rust-hir-trait-ref.h"
+#include "rust-hir-trait-reference.h"
#include "rust-autoderef.h"
namespace Rust {
@@ -38,37 +38,17 @@ public:
TRAIT_ITEM,
};
- TypeCheckContextItem (HIR::Function *item)
- : type (ItemType::ITEM), item (item)
- {}
+ TypeCheckContextItem (HIR::Function *item);
+ TypeCheckContextItem (HIR::ImplBlock *impl_block, HIR::Function *item);
+ TypeCheckContextItem (HIR::TraitItemFunc *trait_item);
- TypeCheckContextItem (HIR::ImplBlock *impl_block, HIR::Function *item)
- : type (ItemType::IMPL_ITEM), item (impl_block, item)
- {}
+ ItemType get_type () const;
- TypeCheckContextItem (HIR::TraitItemFunc *trait_item)
- : type (ItemType::TRAIT_ITEM), item (trait_item)
- {}
+ HIR::Function *get_item ();
- ItemType get_type () const { return type; }
+ std::pair<HIR::ImplBlock *, HIR::Function *> &get_impl_item ();
- HIR::Function *get_item ()
- {
- rust_assert (get_type () == ItemType::ITEM);
- return item.item;
- }
-
- std::pair<HIR::ImplBlock *, HIR::Function *> &get_impl_item ()
- {
- rust_assert (get_type () == ItemType::IMPL_ITEM);
- return item.impl_item;
- };
-
- HIR::TraitItemFunc *get_trait_item ()
- {
- rust_assert (get_type () == ItemType::TRAIT_ITEM);
- return item.trait_item;
- }
+ HIR::TraitItemFunc *get_trait_item ();
TyTy::FnType *get_context_type ();
@@ -79,13 +59,9 @@ private:
std::pair<HIR::ImplBlock *, HIR::Function *> impl_item;
HIR::TraitItemFunc *trait_item;
- Item (HIR::Function *item) : item (item) {}
-
- Item (HIR::ImplBlock *impl_block, HIR::Function *item)
- : impl_item ({impl_block, item})
- {}
-
- Item (HIR::TraitItemFunc *trait_item) : trait_item (trait_item) {}
+ Item (HIR::Function *item);
+ Item (HIR::ImplBlock *impl_block, HIR::Function *item);
+ Item (HIR::TraitItemFunc *trait_item);
};
ItemType type;
@@ -118,283 +94,71 @@ public:
void push_return_type (TypeCheckContextItem item,
TyTy::BaseType *return_type);
void pop_return_type ();
+ void iterate (std::function<bool (HirId, TyTy::BaseType *)> cb);
- void iterate (std::function<bool (HirId, TyTy::BaseType *)> cb)
- {
- for (auto it = resolved.begin (); it != resolved.end (); it++)
- {
- if (!cb (it->first, it->second))
- return;
- }
- }
-
- bool have_loop_context () const { return !loop_type_stack.empty (); }
-
- void push_new_loop_context (HirId id, Location locus)
- {
- TyTy::BaseType *infer_var
- = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL,
- locus);
- loop_type_stack.push_back (infer_var);
- }
-
- void push_new_while_loop_context (HirId id)
- {
- TyTy::BaseType *infer_var = new TyTy::ErrorType (id);
- loop_type_stack.push_back (infer_var);
- }
-
- TyTy::BaseType *peek_loop_context () { return loop_type_stack.back (); }
-
- TyTy::BaseType *pop_loop_context ()
- {
- auto back = peek_loop_context ();
- loop_type_stack.pop_back ();
- return back;
- }
-
- void swap_head_loop_context (TyTy::BaseType *val)
- {
- loop_type_stack.pop_back ();
- loop_type_stack.push_back (val);
- }
-
- void insert_trait_reference (DefId id, TraitReference &&ref)
- {
- rust_assert (trait_context.find (id) == trait_context.end ());
- trait_context.emplace (id, std::move (ref));
- }
-
- bool lookup_trait_reference (DefId id, TraitReference **ref)
- {
- auto it = trait_context.find (id);
- if (it == trait_context.end ())
- return false;
+ bool have_loop_context () const;
+ void push_new_loop_context (HirId id, Location locus);
+ void push_new_while_loop_context (HirId id);
+ TyTy::BaseType *peek_loop_context ();
+ TyTy::BaseType *pop_loop_context ();
- *ref = &it->second;
- return true;
- }
-
- void insert_receiver (HirId id, TyTy::BaseType *t)
- {
- receiver_context[id] = t;
- }
+ void swap_head_loop_context (TyTy::BaseType *val);
- bool lookup_receiver (HirId id, TyTy::BaseType **ref)
- {
- auto it = receiver_context.find (id);
- if (it == receiver_context.end ())
- return false;
+ void insert_trait_reference (DefId id, TraitReference &&ref);
+ bool lookup_trait_reference (DefId id, TraitReference **ref);
- *ref = it->second;
- return true;
- }
+ void insert_receiver (HirId id, TyTy::BaseType *t);
+ bool lookup_receiver (HirId id, TyTy::BaseType **ref);
- void insert_associated_trait_impl (HirId id, AssociatedImplTrait &&associated)
- {
- rust_assert (associated_impl_traits.find (id)
- == associated_impl_traits.end ());
- associated_impl_traits.emplace (id, std::move (associated));
- }
+ void insert_associated_trait_impl (HirId id,
+ AssociatedImplTrait &&associated);
+ bool lookup_associated_trait_impl (HirId id,
+ AssociatedImplTrait **associated);
- bool lookup_associated_trait_impl (HirId id, AssociatedImplTrait **associated)
- {
- auto it = associated_impl_traits.find (id);
- if (it == associated_impl_traits.end ())
- return false;
-
- *associated = &it->second;
- return true;
- }
-
- void insert_associated_type_mapping (HirId id, HirId mapping)
- {
- associated_type_mappings[id] = mapping;
- }
-
- void clear_associated_type_mapping (HirId id)
- {
- auto it = associated_type_mappings.find (id);
- if (it != associated_type_mappings.end ())
- associated_type_mappings.erase (it);
- }
+ void insert_associated_type_mapping (HirId id, HirId mapping);
+ void clear_associated_type_mapping (HirId id);
// lookup any associated type mappings, the out parameter of mapping is
// allowed to be nullptr which allows this interface to do a simple does exist
// check
- bool lookup_associated_type_mapping (HirId id, HirId *mapping)
- {
- auto it = associated_type_mappings.find (id);
- if (it == associated_type_mappings.end ())
- return false;
-
- if (mapping != nullptr)
- *mapping = it->second;
-
- return true;
- }
+ bool lookup_associated_type_mapping (HirId id, HirId *mapping);
void insert_associated_impl_mapping (HirId trait_id,
const TyTy::BaseType *impl_type,
- HirId impl_id)
- {
- auto it = associated_traits_to_impls.find (trait_id);
- if (it == associated_traits_to_impls.end ())
- {
- associated_traits_to_impls[trait_id] = {};
- }
-
- associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id});
- }
-
+ HirId impl_id);
bool lookup_associated_impl_mapping_for_self (HirId trait_id,
const TyTy::BaseType *self,
- HirId *mapping)
- {
- auto it = associated_traits_to_impls.find (trait_id);
- if (it == associated_traits_to_impls.end ())
- return false;
-
- for (auto &item : it->second)
- {
- if (item.first->can_eq (self, false))
- {
- *mapping = item.second;
- return true;
- }
- }
- return false;
- }
+ HirId *mapping);
void insert_autoderef_mappings (HirId id,
- std::vector<Adjustment> &&adjustments)
- {
- rust_assert (autoderef_mappings.find (id) == autoderef_mappings.end ());
- autoderef_mappings.emplace (id, std::move (adjustments));
- }
-
+ std::vector<Adjustment> &&adjustments);
bool lookup_autoderef_mappings (HirId id,
- std::vector<Adjustment> **adjustments)
- {
- auto it = autoderef_mappings.find (id);
- if (it == autoderef_mappings.end ())
- return false;
-
- *adjustments = &it->second;
- return true;
- }
+ std::vector<Adjustment> **adjustments);
void insert_cast_autoderef_mappings (HirId id,
- std::vector<Adjustment> &&adjustments)
- {
- rust_assert (cast_autoderef_mappings.find (id)
- == cast_autoderef_mappings.end ());
- cast_autoderef_mappings.emplace (id, std::move (adjustments));
- }
-
+ std::vector<Adjustment> &&adjustments);
bool lookup_cast_autoderef_mappings (HirId id,
- std::vector<Adjustment> **adjustments)
- {
- auto it = cast_autoderef_mappings.find (id);
- if (it == cast_autoderef_mappings.end ())
- return false;
+ std::vector<Adjustment> **adjustments);
- *adjustments = &it->second;
- return true;
- }
+ void insert_variant_definition (HirId id, HirId variant);
+ bool lookup_variant_definition (HirId id, HirId *variant);
- void insert_variant_definition (HirId id, HirId variant)
- {
- auto it = variants.find (id);
- rust_assert (it == variants.end ());
+ void insert_operator_overload (HirId id, TyTy::FnType *call_site);
+ bool lookup_operator_overload (HirId id, TyTy::FnType **call);
- variants[id] = variant;
- }
+ void insert_unconstrained_check_marker (HirId id, bool status);
+ bool have_checked_for_unconstrained (HirId id, bool *result);
- bool lookup_variant_definition (HirId id, HirId *variant)
- {
- auto it = variants.find (id);
- if (it == variants.end ())
- return false;
+ void insert_resolved_predicate (HirId id, TyTy::TypeBoundPredicate predicate);
+ bool lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result);
- *variant = it->second;
- return true;
- }
-
- void insert_operator_overload (HirId id, TyTy::FnType *call_site)
- {
- auto it = operator_overloads.find (id);
- rust_assert (it == operator_overloads.end ());
-
- operator_overloads[id] = call_site;
- }
-
- bool lookup_operator_overload (HirId id, TyTy::FnType **call)
- {
- auto it = operator_overloads.find (id);
- if (it == operator_overloads.end ())
- return false;
-
- *call = it->second;
- return true;
- }
+ void insert_query (HirId id);
+ void query_completed (HirId id);
+ bool query_in_progress (HirId id) const;
- void insert_unconstrained_check_marker (HirId id, bool status)
- {
- unconstrained[id] = status;
- }
-
- bool have_checked_for_unconstrained (HirId id, bool *result)
- {
- auto it = unconstrained.find (id);
- bool found = it != unconstrained.end ();
- if (!found)
- return false;
-
- *result = it->second;
- return true;
- }
-
- void insert_resolved_predicate (HirId id, TyTy::TypeBoundPredicate predicate)
- {
- auto it = predicates.find (id);
- rust_assert (it == predicates.end ());
-
- predicates.insert ({id, predicate});
- }
-
- bool lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result)
- {
- auto it = predicates.find (id);
- bool found = it != predicates.end ();
- if (!found)
- return false;
-
- *result = it->second;
- return true;
- }
-
- void insert_query (HirId id) { querys_in_progress.insert (id); }
-
- void query_completed (HirId id) { querys_in_progress.erase (id); }
-
- bool query_in_progress (HirId id) const
- {
- return querys_in_progress.find (id) != querys_in_progress.end ();
- }
-
- void insert_trait_query (DefId id) { trait_queries_in_progress.insert (id); }
-
- void trait_query_completed (DefId id)
- {
- trait_queries_in_progress.erase (id);
- }
-
- bool trait_query_in_progress (DefId id) const
- {
- return trait_queries_in_progress.find (id)
- != trait_queries_in_progress.end ();
- }
+ void insert_trait_query (DefId id);
+ void trait_query_completed (DefId id);
+ bool trait_query_in_progress (DefId id) const;
private:
TypeCheckContext ();
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc b/gcc/rust/typecheck/rust-substitution-mapper.cc
index f80368a..9ccb80b 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.cc
+++ b/gcc/rust/typecheck/rust-substitution-mapper.cc
@@ -22,6 +22,116 @@
namespace Rust {
namespace Resolver {
+SubstMapper::SubstMapper (HirId ref, HIR::GenericArgs *generics, Location locus)
+ : resolved (new TyTy::ErrorType (ref)), generics (generics), locus (locus)
+{}
+
+TyTy::BaseType *
+SubstMapper::Resolve (TyTy::BaseType *base, Location locus,
+ HIR::GenericArgs *generics)
+{
+ SubstMapper mapper (base->get_ref (), generics, locus);
+ base->accept_vis (mapper);
+ rust_assert (mapper.resolved != nullptr);
+ return mapper.resolved;
+}
+
+TyTy::BaseType *
+SubstMapper::InferSubst (TyTy::BaseType *base, Location locus)
+{
+ return SubstMapper::Resolve (base, locus, nullptr);
+}
+
+bool
+SubstMapper::have_generic_args () const
+{
+ return generics != nullptr;
+}
+
+void
+SubstMapper::visit (TyTy::FnType &type)
+{
+ TyTy::FnType *concrete = nullptr;
+ if (!have_generic_args ())
+ {
+ TyTy::BaseType *substs = type.infer_substitions (locus);
+ rust_assert (substs->get_kind () == TyTy::TypeKind::FNDEF);
+ concrete = static_cast<TyTy::FnType *> (substs);
+ }
+ else
+ {
+ TyTy::SubstitutionArgumentMappings mappings
+ = type.get_mappings_from_generic_args (*generics);
+ if (mappings.is_error ())
+ return;
+
+ concrete = type.handle_substitions (mappings);
+ }
+
+ if (concrete != nullptr)
+ resolved = concrete;
+}
+
+void
+SubstMapper::visit (TyTy::ADTType &type)
+{
+ TyTy::ADTType *concrete = nullptr;
+ if (!have_generic_args ())
+ {
+ TyTy::BaseType *substs = type.infer_substitions (locus);
+ rust_assert (substs->get_kind () == TyTy::TypeKind::ADT);
+ concrete = static_cast<TyTy::ADTType *> (substs);
+ }
+ else
+ {
+ TyTy::SubstitutionArgumentMappings mappings
+ = type.get_mappings_from_generic_args (*generics);
+ if (mappings.is_error ())
+ return;
+
+ concrete = type.handle_substitions (mappings);
+ }
+
+ if (concrete != nullptr)
+ resolved = concrete;
+}
+
+void
+SubstMapper::visit (TyTy::PlaceholderType &type)
+{
+ rust_assert (type.can_resolve ());
+ resolved = SubstMapper::Resolve (type.resolve (), locus, generics);
+}
+
+void
+SubstMapper::visit (TyTy::ProjectionType &type)
+{
+ TyTy::ProjectionType *concrete = nullptr;
+ if (!have_generic_args ())
+ {
+ TyTy::BaseType *substs = type.infer_substitions (locus);
+ rust_assert (substs->get_kind () == TyTy::TypeKind::PROJECTION);
+ concrete = static_cast<TyTy::ProjectionType *> (substs);
+ }
+ else
+ {
+ TyTy::SubstitutionArgumentMappings mappings
+ = type.get_mappings_from_generic_args (*generics);
+ if (mappings.is_error ())
+ return;
+
+ concrete = type.handle_substitions (mappings);
+ }
+
+ if (concrete != nullptr)
+ resolved = concrete;
+}
+
+SubstMapperInternal::SubstMapperInternal (
+ HirId ref, TyTy::SubstitutionArgumentMappings &mappings)
+ : resolved (new TyTy::ErrorType (ref)), mappings (mappings)
+{}
+
TyTy::BaseType *
SubstMapperInternal::Resolve (TyTy::BaseType *base,
TyTy::SubstitutionArgumentMappings &mappings)
@@ -73,5 +183,238 @@ SubstMapperInternal::mappings_are_bound (
return false;
}
+void
+SubstMapperInternal::visit (TyTy::FnType &type)
+{
+ TyTy::SubstitutionArgumentMappings adjusted
+ = type.adjust_mappings_for_this (mappings);
+ if (adjusted.is_error ())
+ return;
+
+ TyTy::BaseType *concrete = type.handle_substitions (adjusted);
+ if (concrete != nullptr)
+ resolved = concrete;
+}
+
+void
+SubstMapperInternal::visit (TyTy::ADTType &type)
+{
+ TyTy::SubstitutionArgumentMappings adjusted
+ = type.adjust_mappings_for_this (mappings);
+ if (adjusted.is_error ())
+ return;
+
+ TyTy::BaseType *concrete = type.handle_substitions (adjusted);
+ if (concrete != nullptr)
+ resolved = concrete;
+}
+
+// these don't support generic arguments but might contain a type param
+void
+SubstMapperInternal::visit (TyTy::TupleType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::ReferenceType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::PointerType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::ParamType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::PlaceholderType &type)
+{
+ rust_assert (type.can_resolve ());
+ if (mappings.trait_item_mode ())
+ {
+ resolved = type.resolve ();
+ }
+ else
+ {
+ resolved = SubstMapperInternal::Resolve (type.resolve (), mappings);
+ }
+}
+
+void
+SubstMapperInternal::visit (TyTy::ProjectionType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::ClosureType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::ArrayType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::SliceType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+// nothing to do for these
+void
+SubstMapperInternal::visit (TyTy::InferType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::FnPtr &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::BoolType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::IntType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::UintType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::FloatType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::USizeType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::ISizeType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::ErrorType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::CharType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::StrType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::NeverType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::DynamicObjectType &type)
+{
+ resolved = type.clone ();
+}
+
+// SubstMapperFromExisting
+
+SubstMapperFromExisting::SubstMapperFromExisting (TyTy::BaseType *concrete,
+ TyTy::BaseType *receiver)
+ : concrete (concrete), receiver (receiver), resolved (nullptr)
+{}
+
+TyTy::BaseType *
+SubstMapperFromExisting::Resolve (TyTy::BaseType *concrete,
+ TyTy::BaseType *receiver)
+{
+ rust_assert (concrete->get_kind () == receiver->get_kind ());
+
+ SubstMapperFromExisting mapper (concrete, receiver);
+ concrete->accept_vis (mapper);
+ return mapper.resolved;
+}
+
+void
+SubstMapperFromExisting::visit (TyTy::FnType &type)
+{
+ rust_assert (type.was_substituted ());
+
+ TyTy::FnType *to_sub = static_cast<TyTy::FnType *> (receiver);
+ resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
+}
+
+void
+SubstMapperFromExisting::visit (TyTy::ADTType &type)
+{
+ rust_assert (type.was_substituted ());
+
+ TyTy::ADTType *to_sub = static_cast<TyTy::ADTType *> (receiver);
+ resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
+}
+
+void
+SubstMapperFromExisting::visit (TyTy::ClosureType &type)
+{
+ rust_assert (type.was_substituted ());
+
+ TyTy::ClosureType *to_sub = static_cast<TyTy::ClosureType *> (receiver);
+ resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
+}
+
+// GetUsedSubstArgs
+
+GetUsedSubstArgs::GetUsedSubstArgs ()
+ : args (TyTy::SubstitutionArgumentMappings::error ())
+{}
+
+TyTy::SubstitutionArgumentMappings
+GetUsedSubstArgs::From (const TyTy::BaseType *from)
+{
+ GetUsedSubstArgs mapper;
+ from->accept_vis (mapper);
+ return mapper.args;
+}
+
+void
+GetUsedSubstArgs::visit (const TyTy::FnType &type)
+{
+ args = type.get_substitution_arguments ();
+}
+
+void
+GetUsedSubstArgs::visit (const TyTy::ADTType &type)
+{
+ args = type.get_substitution_arguments ();
+}
+
+void
+GetUsedSubstArgs::visit (const TyTy::ClosureType &type)
+{
+ args = type.get_substitution_arguments ();
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h
index e326bbd..047034e 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.h
+++ b/gcc/rust/typecheck/rust-substitution-mapper.h
@@ -29,95 +29,16 @@ class SubstMapper : public TyTy::TyVisitor
{
public:
static TyTy::BaseType *Resolve (TyTy::BaseType *base, Location locus,
- HIR::GenericArgs *generics = nullptr)
- {
- SubstMapper mapper (base->get_ref (), generics, locus);
- base->accept_vis (mapper);
- rust_assert (mapper.resolved != nullptr);
- return mapper.resolved;
- }
+ HIR::GenericArgs *generics = nullptr);
- static TyTy::BaseType *InferSubst (TyTy::BaseType *base, Location locus)
- {
- return SubstMapper::Resolve (base, locus, nullptr);
- }
+ static TyTy::BaseType *InferSubst (TyTy::BaseType *base, Location locus);
- bool have_generic_args () const { return generics != nullptr; }
+ bool have_generic_args () const;
- void visit (TyTy::FnType &type) override
- {
- TyTy::FnType *concrete = nullptr;
- if (!have_generic_args ())
- {
- TyTy::BaseType *substs = type.infer_substitions (locus);
- rust_assert (substs->get_kind () == TyTy::TypeKind::FNDEF);
- concrete = static_cast<TyTy::FnType *> (substs);
- }
- else
- {
- TyTy::SubstitutionArgumentMappings mappings
- = type.get_mappings_from_generic_args (*generics);
- if (mappings.is_error ())
- return;
-
- concrete = type.handle_substitions (mappings);
- }
-
- if (concrete != nullptr)
- resolved = concrete;
- }
-
- void visit (TyTy::ADTType &type) override
- {
- TyTy::ADTType *concrete = nullptr;
- if (!have_generic_args ())
- {
- TyTy::BaseType *substs = type.infer_substitions (locus);
- rust_assert (substs->get_kind () == TyTy::TypeKind::ADT);
- concrete = static_cast<TyTy::ADTType *> (substs);
- }
- else
- {
- TyTy::SubstitutionArgumentMappings mappings
- = type.get_mappings_from_generic_args (*generics);
- if (mappings.is_error ())
- return;
-
- concrete = type.handle_substitions (mappings);
- }
-
- if (concrete != nullptr)
- resolved = concrete;
- }
-
- void visit (TyTy::PlaceholderType &type) override
- {
- rust_assert (type.can_resolve ());
- resolved = SubstMapper::Resolve (type.resolve (), locus, generics);
- }
-
- void visit (TyTy::ProjectionType &type) override
- {
- TyTy::ProjectionType *concrete = nullptr;
- if (!have_generic_args ())
- {
- TyTy::BaseType *substs = type.infer_substitions (locus);
- rust_assert (substs->get_kind () == TyTy::TypeKind::PROJECTION);
- concrete = static_cast<TyTy::ProjectionType *> (substs);
- }
- else
- {
- TyTy::SubstitutionArgumentMappings mappings
- = type.get_mappings_from_generic_args (*generics);
- if (mappings.is_error ())
- return;
-
- concrete = type.handle_substitions (mappings);
- }
-
- if (concrete != nullptr)
- resolved = concrete;
- }
+ void visit (TyTy::FnType &type) override;
+ void visit (TyTy::ADTType &type) override;
+ void visit (TyTy::PlaceholderType &type) override;
+ void visit (TyTy::ProjectionType &type) override;
// nothing to do for these
void visit (TyTy::InferType &) override { gcc_unreachable (); }
@@ -142,9 +63,7 @@ public:
void visit (TyTy::ClosureType &) override { gcc_unreachable (); }
private:
- SubstMapper (HirId ref, HIR::GenericArgs *generics, Location locus)
- : resolved (new TyTy::ErrorType (ref)), generics (generics), locus (locus)
- {}
+ SubstMapper (HirId ref, HIR::GenericArgs *generics, Location locus);
TyTy::BaseType *resolved;
HIR::GenericArgs *generics;
@@ -160,106 +79,33 @@ public:
static bool mappings_are_bound (TyTy::BaseType *ty,
TyTy::SubstitutionArgumentMappings &mappings);
- void visit (TyTy::FnType &type) override
- {
- TyTy::SubstitutionArgumentMappings adjusted
- = type.adjust_mappings_for_this (mappings);
- if (adjusted.is_error ())
- return;
-
- TyTy::BaseType *concrete = type.handle_substitions (adjusted);
- if (concrete != nullptr)
- resolved = concrete;
- }
-
- void visit (TyTy::ADTType &type) override
- {
- TyTy::SubstitutionArgumentMappings adjusted
- = type.adjust_mappings_for_this (mappings);
- if (adjusted.is_error ())
- return;
-
- TyTy::BaseType *concrete = type.handle_substitions (adjusted);
- if (concrete != nullptr)
- resolved = concrete;
- }
-
- // these don't support generic arguments but might contain a type param
- void visit (TyTy::TupleType &type) override
- {
- resolved = type.handle_substitions (mappings);
- }
-
- void visit (TyTy::ReferenceType &type) override
- {
- resolved = type.handle_substitions (mappings);
- }
-
- void visit (TyTy::PointerType &type) override
- {
- resolved = type.handle_substitions (mappings);
- }
-
- void visit (TyTy::ParamType &type) override
- {
- resolved = type.handle_substitions (mappings);
- }
-
- void visit (TyTy::PlaceholderType &type) override
- {
- rust_assert (type.can_resolve ());
- if (mappings.trait_item_mode ())
- {
- resolved = type.resolve ();
- }
- else
- {
- resolved = SubstMapperInternal::Resolve (type.resolve (), mappings);
- }
- }
-
- void visit (TyTy::ProjectionType &type) override
- {
- resolved = type.handle_substitions (mappings);
- }
-
- void visit (TyTy::ClosureType &type) override
- {
- resolved = type.handle_substitions (mappings);
- }
-
- void visit (TyTy::ArrayType &type) override
- {
- resolved = type.handle_substitions (mappings);
- }
-
- void visit (TyTy::SliceType &type) override
- {
- resolved = type.handle_substitions (mappings);
- }
-
- // nothing to do for these
- void visit (TyTy::InferType &type) override { resolved = type.clone (); }
- void visit (TyTy::FnPtr &type) override { resolved = type.clone (); }
- void visit (TyTy::BoolType &type) override { resolved = type.clone (); }
- void visit (TyTy::IntType &type) override { resolved = type.clone (); }
- void visit (TyTy::UintType &type) override { resolved = type.clone (); }
- void visit (TyTy::FloatType &type) override { resolved = type.clone (); }
- void visit (TyTy::USizeType &type) override { resolved = type.clone (); }
- void visit (TyTy::ISizeType &type) override { resolved = type.clone (); }
- void visit (TyTy::ErrorType &type) override { resolved = type.clone (); }
- void visit (TyTy::CharType &type) override { resolved = type.clone (); }
- void visit (TyTy::StrType &type) override { resolved = type.clone (); }
- void visit (TyTy::NeverType &type) override { resolved = type.clone (); }
- void visit (TyTy::DynamicObjectType &type) override
- {
- resolved = type.clone ();
- }
+ void visit (TyTy::FnType &type) override;
+ void visit (TyTy::ADTType &type) override;
+ void visit (TyTy::TupleType &type) override;
+ void visit (TyTy::ReferenceType &type) override;
+ void visit (TyTy::PointerType &type) override;
+ void visit (TyTy::ParamType &type) override;
+ void visit (TyTy::PlaceholderType &type) override;
+ void visit (TyTy::ProjectionType &type) override;
+ void visit (TyTy::ClosureType &type) override;
+ void visit (TyTy::ArrayType &type) override;
+ void visit (TyTy::SliceType &type) override;
+ void visit (TyTy::InferType &type) override;
+ void visit (TyTy::FnPtr &type) override;
+ void visit (TyTy::BoolType &type) override;
+ void visit (TyTy::IntType &type) override;
+ void visit (TyTy::UintType &type) override;
+ void visit (TyTy::FloatType &type) override;
+ void visit (TyTy::USizeType &type) override;
+ void visit (TyTy::ISizeType &type) override;
+ void visit (TyTy::ErrorType &type) override;
+ void visit (TyTy::CharType &type) override;
+ void visit (TyTy::StrType &type) override;
+ void visit (TyTy::NeverType &type) override;
+ void visit (TyTy::DynamicObjectType &type) override;
private:
- SubstMapperInternal (HirId ref, TyTy::SubstitutionArgumentMappings &mappings)
- : resolved (new TyTy::ErrorType (ref)), mappings (mappings)
- {}
+ SubstMapperInternal (HirId ref, TyTy::SubstitutionArgumentMappings &mappings);
TyTy::BaseType *resolved;
TyTy::SubstitutionArgumentMappings &mappings;
@@ -269,38 +115,11 @@ class SubstMapperFromExisting : public TyTy::TyVisitor
{
public:
static TyTy::BaseType *Resolve (TyTy::BaseType *concrete,
- TyTy::BaseType *receiver)
- {
- rust_assert (concrete->get_kind () == receiver->get_kind ());
-
- SubstMapperFromExisting mapper (concrete, receiver);
- concrete->accept_vis (mapper);
- return mapper.resolved;
- }
+ TyTy::BaseType *receiver);
- void visit (TyTy::FnType &type) override
- {
- rust_assert (type.was_substituted ());
-
- TyTy::FnType *to_sub = static_cast<TyTy::FnType *> (receiver);
- resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
- }
-
- void visit (TyTy::ADTType &type) override
- {
- rust_assert (type.was_substituted ());
-
- TyTy::ADTType *to_sub = static_cast<TyTy::ADTType *> (receiver);
- resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
- }
-
- void visit (TyTy::ClosureType &type) override
- {
- rust_assert (type.was_substituted ());
-
- TyTy::ClosureType *to_sub = static_cast<TyTy::ClosureType *> (receiver);
- resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
- }
+ void visit (TyTy::FnType &type) override;
+ void visit (TyTy::ADTType &type) override;
+ void visit (TyTy::ClosureType &type) override;
void visit (TyTy::InferType &) override { gcc_unreachable (); }
void visit (TyTy::TupleType &) override { gcc_unreachable (); }
@@ -325,40 +144,21 @@ public:
void visit (TyTy::DynamicObjectType &) override { gcc_unreachable (); }
private:
- SubstMapperFromExisting (TyTy::BaseType *concrete, TyTy::BaseType *receiver)
- : concrete (concrete), receiver (receiver), resolved (nullptr)
- {}
+ SubstMapperFromExisting (TyTy::BaseType *concrete, TyTy::BaseType *receiver);
TyTy::BaseType *concrete;
TyTy::BaseType *receiver;
-
TyTy::BaseType *resolved;
};
class GetUsedSubstArgs : public TyTy::TyConstVisitor
{
public:
- static TyTy::SubstitutionArgumentMappings From (const TyTy::BaseType *from)
- {
- GetUsedSubstArgs mapper;
- from->accept_vis (mapper);
- return mapper.args;
- }
-
- void visit (const TyTy::FnType &type) override
- {
- args = type.get_substitution_arguments ();
- }
-
- void visit (const TyTy::ADTType &type) override
- {
- args = type.get_substitution_arguments ();
- }
+ static TyTy::SubstitutionArgumentMappings From (const TyTy::BaseType *from);
- void visit (const TyTy::ClosureType &type) override
- {
- args = type.get_substitution_arguments ();
- }
+ void visit (const TyTy::FnType &type) override;
+ void visit (const TyTy::ADTType &type) override;
+ void visit (const TyTy::ClosureType &type) override;
void visit (const TyTy::InferType &) override {}
void visit (const TyTy::TupleType &) override {}
@@ -383,7 +183,7 @@ public:
void visit (const TyTy::DynamicObjectType &) override {}
private:
- GetUsedSubstArgs () : args (TyTy::SubstitutionArgumentMappings::error ()) {}
+ GetUsedSubstArgs ();
TyTy::SubstitutionArgumentMappings args;
};
diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc
deleted file mode 100644
index 34b60b3..0000000
--- a/gcc/rust/typecheck/rust-tyctx.cc
+++ /dev/null
@@ -1,190 +0,0 @@
-// 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-hir-type-check.h"
-
-namespace Rust {
-namespace Resolver {
-
-TypeCheckContext *
-TypeCheckContext::get ()
-{
- static TypeCheckContext *instance;
- if (instance == nullptr)
- instance = new TypeCheckContext ();
-
- return instance;
-}
-
-TypeCheckContext::TypeCheckContext () {}
-
-TypeCheckContext::~TypeCheckContext () {}
-
-bool
-TypeCheckContext::lookup_builtin (NodeId id, TyTy::BaseType **type)
-{
- auto ref_it = node_id_refs.find (id);
- if (ref_it == node_id_refs.end ())
- return false;
-
- auto it = resolved.find (ref_it->second);
- if (it == resolved.end ())
- return false;
-
- *type = it->second;
- return true;
-}
-
-bool
-TypeCheckContext::lookup_builtin (std::string name, TyTy::BaseType **type)
-{
- for (auto &builtin : builtins)
- {
- if (name.compare (builtin->as_string ()) == 0)
- {
- *type = builtin.get ();
- return true;
- }
- }
- return false;
-}
-
-void
-TypeCheckContext::insert_builtin (HirId id, NodeId ref, TyTy::BaseType *type)
-{
- node_id_refs[ref] = id;
- resolved[id] = type;
- builtins.push_back (std::unique_ptr<TyTy::BaseType> (type));
-}
-
-void
-TypeCheckContext::insert_type (const Analysis::NodeMapping &mappings,
- TyTy::BaseType *type)
-{
- rust_assert (type != nullptr);
- NodeId ref = mappings.get_nodeid ();
- HirId id = mappings.get_hirid ();
- node_id_refs[ref] = id;
- resolved[id] = type;
-}
-
-void
-TypeCheckContext::insert_implicit_type (TyTy::BaseType *type)
-{
- rust_assert (type != nullptr);
- resolved[type->get_ref ()] = type;
-}
-
-void
-TypeCheckContext::insert_implicit_type (HirId id, TyTy::BaseType *type)
-{
- rust_assert (type != nullptr);
- resolved[id] = type;
-}
-
-bool
-TypeCheckContext::lookup_type (HirId id, TyTy::BaseType **type) const
-{
- auto it = resolved.find (id);
- if (it == resolved.end ())
- return false;
-
- *type = it->second;
- return true;
-}
-
-void
-TypeCheckContext::insert_type_by_node_id (NodeId ref, HirId id)
-{
- rust_assert (node_id_refs.find (ref) == node_id_refs.end ());
- node_id_refs[ref] = id;
-}
-
-bool
-TypeCheckContext::lookup_type_by_node_id (NodeId ref, HirId *id)
-{
- auto it = node_id_refs.find (ref);
- if (it == node_id_refs.end ())
- return false;
-
- *id = it->second;
- return true;
-}
-
-TyTy::BaseType *
-TypeCheckContext::peek_return_type ()
-{
- rust_assert (!return_type_stack.empty ());
- return return_type_stack.back ().second;
-}
-
-void
-TypeCheckContext::push_return_type (TypeCheckContextItem item,
- TyTy::BaseType *return_type)
-{
- return_type_stack.push_back ({std::move (item), return_type});
-}
-
-void
-TypeCheckContext::pop_return_type ()
-{
- rust_assert (!return_type_stack.empty ());
- return_type_stack.pop_back ();
-}
-
-TypeCheckContextItem &
-TypeCheckContext::peek_context ()
-{
- rust_assert (!return_type_stack.empty ());
- return return_type_stack.back ().first;
-}
-
-// TypeCheckContextItem
-
-TyTy::FnType *
-TypeCheckContextItem::get_context_type ()
-{
- auto &context = *TypeCheckContext::get ();
-
- HirId reference = UNKNOWN_HIRID;
- switch (get_type ())
- {
- case ITEM:
- reference = get_item ()->get_mappings ().get_hirid ();
- break;
-
- case IMPL_ITEM:
- reference = get_impl_item ().second->get_mappings ().get_hirid ();
- break;
-
- case TRAIT_ITEM:
- reference = get_trait_item ()->get_mappings ().get_hirid ();
- break;
- }
-
- rust_assert (reference != UNKNOWN_HIRID);
-
- TyTy::BaseType *lookup = nullptr;
- bool ok = context.lookup_type (reference, &lookup);
- rust_assert (ok);
- rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
- return static_cast<TyTy::FnType *> (lookup);
-}
-
-} // namespace Resolver
-} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-typecheck-context.cc b/gcc/rust/typecheck/rust-typecheck-context.cc
new file mode 100644
index 0000000..ba4d322
--- /dev/null
+++ b/gcc/rust/typecheck/rust-typecheck-context.cc
@@ -0,0 +1,569 @@
+// 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-hir-type-check.h"
+
+namespace Rust {
+namespace Resolver {
+
+TypeCheckContext *
+TypeCheckContext::get ()
+{
+ static TypeCheckContext *instance;
+ if (instance == nullptr)
+ instance = new TypeCheckContext ();
+
+ return instance;
+}
+
+TypeCheckContext::TypeCheckContext () {}
+
+TypeCheckContext::~TypeCheckContext () {}
+
+bool
+TypeCheckContext::lookup_builtin (NodeId id, TyTy::BaseType **type)
+{
+ auto ref_it = node_id_refs.find (id);
+ if (ref_it == node_id_refs.end ())
+ return false;
+
+ auto it = resolved.find (ref_it->second);
+ if (it == resolved.end ())
+ return false;
+
+ *type = it->second;
+ return true;
+}
+
+bool
+TypeCheckContext::lookup_builtin (std::string name, TyTy::BaseType **type)
+{
+ for (auto &builtin : builtins)
+ {
+ if (name.compare (builtin->as_string ()) == 0)
+ {
+ *type = builtin.get ();
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+TypeCheckContext::insert_builtin (HirId id, NodeId ref, TyTy::BaseType *type)
+{
+ node_id_refs[ref] = id;
+ resolved[id] = type;
+ builtins.push_back (std::unique_ptr<TyTy::BaseType> (type));
+}
+
+void
+TypeCheckContext::insert_type (const Analysis::NodeMapping &mappings,
+ TyTy::BaseType *type)
+{
+ rust_assert (type != nullptr);
+ NodeId ref = mappings.get_nodeid ();
+ HirId id = mappings.get_hirid ();
+ node_id_refs[ref] = id;
+ resolved[id] = type;
+}
+
+void
+TypeCheckContext::insert_implicit_type (TyTy::BaseType *type)
+{
+ rust_assert (type != nullptr);
+ resolved[type->get_ref ()] = type;
+}
+
+void
+TypeCheckContext::insert_implicit_type (HirId id, TyTy::BaseType *type)
+{
+ rust_assert (type != nullptr);
+ resolved[id] = type;
+}
+
+bool
+TypeCheckContext::lookup_type (HirId id, TyTy::BaseType **type) const
+{
+ auto it = resolved.find (id);
+ if (it == resolved.end ())
+ return false;
+
+ *type = it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_type_by_node_id (NodeId ref, HirId id)
+{
+ rust_assert (node_id_refs.find (ref) == node_id_refs.end ());
+ node_id_refs[ref] = id;
+}
+
+bool
+TypeCheckContext::lookup_type_by_node_id (NodeId ref, HirId *id)
+{
+ auto it = node_id_refs.find (ref);
+ if (it == node_id_refs.end ())
+ return false;
+
+ *id = it->second;
+ return true;
+}
+
+TyTy::BaseType *
+TypeCheckContext::peek_return_type ()
+{
+ rust_assert (!return_type_stack.empty ());
+ return return_type_stack.back ().second;
+}
+
+void
+TypeCheckContext::push_return_type (TypeCheckContextItem item,
+ TyTy::BaseType *return_type)
+{
+ return_type_stack.push_back ({std::move (item), return_type});
+}
+
+void
+TypeCheckContext::pop_return_type ()
+{
+ rust_assert (!return_type_stack.empty ());
+ return_type_stack.pop_back ();
+}
+
+TypeCheckContextItem &
+TypeCheckContext::peek_context ()
+{
+ rust_assert (!return_type_stack.empty ());
+ return return_type_stack.back ().first;
+}
+
+void
+TypeCheckContext::iterate (std::function<bool (HirId, TyTy::BaseType *)> cb)
+{
+ for (auto it = resolved.begin (); it != resolved.end (); it++)
+ {
+ if (!cb (it->first, it->second))
+ return;
+ }
+}
+
+bool
+TypeCheckContext::have_loop_context () const
+{
+ return !loop_type_stack.empty ();
+}
+
+void
+TypeCheckContext::push_new_loop_context (HirId id, Location locus)
+{
+ TyTy::BaseType *infer_var
+ = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL, locus);
+ loop_type_stack.push_back (infer_var);
+}
+
+void
+TypeCheckContext::push_new_while_loop_context (HirId id)
+{
+ TyTy::BaseType *infer_var = new TyTy::ErrorType (id);
+ loop_type_stack.push_back (infer_var);
+}
+
+TyTy::BaseType *
+TypeCheckContext::peek_loop_context ()
+{
+ return loop_type_stack.back ();
+}
+
+TyTy::BaseType *
+TypeCheckContext::pop_loop_context ()
+{
+ auto back = peek_loop_context ();
+ loop_type_stack.pop_back ();
+ return back;
+}
+
+void
+TypeCheckContext::swap_head_loop_context (TyTy::BaseType *val)
+{
+ loop_type_stack.pop_back ();
+ loop_type_stack.push_back (val);
+}
+
+void
+TypeCheckContext::insert_trait_reference (DefId id, TraitReference &&ref)
+{
+ rust_assert (trait_context.find (id) == trait_context.end ());
+ trait_context.emplace (id, std::move (ref));
+}
+
+bool
+TypeCheckContext::lookup_trait_reference (DefId id, TraitReference **ref)
+{
+ auto it = trait_context.find (id);
+ if (it == trait_context.end ())
+ return false;
+
+ *ref = &it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_receiver (HirId id, TyTy::BaseType *t)
+{
+ receiver_context[id] = t;
+}
+
+bool
+TypeCheckContext::lookup_receiver (HirId id, TyTy::BaseType **ref)
+{
+ auto it = receiver_context.find (id);
+ if (it == receiver_context.end ())
+ return false;
+
+ *ref = it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_associated_trait_impl (
+ HirId id, AssociatedImplTrait &&associated)
+{
+ rust_assert (associated_impl_traits.find (id)
+ == associated_impl_traits.end ());
+ associated_impl_traits.emplace (id, std::move (associated));
+}
+
+bool
+TypeCheckContext::lookup_associated_trait_impl (
+ HirId id, AssociatedImplTrait **associated)
+{
+ auto it = associated_impl_traits.find (id);
+ if (it == associated_impl_traits.end ())
+ return false;
+
+ *associated = &it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_associated_type_mapping (HirId id, HirId mapping)
+{
+ associated_type_mappings[id] = mapping;
+}
+
+void
+TypeCheckContext::clear_associated_type_mapping (HirId id)
+{
+ auto it = associated_type_mappings.find (id);
+ if (it != associated_type_mappings.end ())
+ associated_type_mappings.erase (it);
+}
+
+// lookup any associated type mappings, the out parameter of mapping is
+// allowed to be nullptr which allows this interface to do a simple does exist
+// check
+bool
+TypeCheckContext::lookup_associated_type_mapping (HirId id, HirId *mapping)
+{
+ auto it = associated_type_mappings.find (id);
+ if (it == associated_type_mappings.end ())
+ return false;
+
+ if (mapping != nullptr)
+ *mapping = it->second;
+
+ return true;
+}
+
+void
+TypeCheckContext::insert_associated_impl_mapping (
+ HirId trait_id, const TyTy::BaseType *impl_type, HirId impl_id)
+{
+ auto it = associated_traits_to_impls.find (trait_id);
+ if (it == associated_traits_to_impls.end ())
+ {
+ associated_traits_to_impls[trait_id] = {};
+ }
+
+ associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id});
+}
+
+bool
+TypeCheckContext::lookup_associated_impl_mapping_for_self (
+ HirId trait_id, const TyTy::BaseType *self, HirId *mapping)
+{
+ auto it = associated_traits_to_impls.find (trait_id);
+ if (it == associated_traits_to_impls.end ())
+ return false;
+
+ for (auto &item : it->second)
+ {
+ if (item.first->can_eq (self, false))
+ {
+ *mapping = item.second;
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+TypeCheckContext::insert_autoderef_mappings (
+ HirId id, std::vector<Adjustment> &&adjustments)
+{
+ rust_assert (autoderef_mappings.find (id) == autoderef_mappings.end ());
+ autoderef_mappings.emplace (id, std::move (adjustments));
+}
+
+bool
+TypeCheckContext::lookup_autoderef_mappings (
+ HirId id, std::vector<Adjustment> **adjustments)
+{
+ auto it = autoderef_mappings.find (id);
+ if (it == autoderef_mappings.end ())
+ return false;
+
+ *adjustments = &it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_cast_autoderef_mappings (
+ HirId id, std::vector<Adjustment> &&adjustments)
+{
+ rust_assert (cast_autoderef_mappings.find (id)
+ == cast_autoderef_mappings.end ());
+ cast_autoderef_mappings.emplace (id, std::move (adjustments));
+}
+
+bool
+TypeCheckContext::lookup_cast_autoderef_mappings (
+ HirId id, std::vector<Adjustment> **adjustments)
+{
+ auto it = cast_autoderef_mappings.find (id);
+ if (it == cast_autoderef_mappings.end ())
+ return false;
+
+ *adjustments = &it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_variant_definition (HirId id, HirId variant)
+{
+ auto it = variants.find (id);
+ rust_assert (it == variants.end ());
+
+ variants[id] = variant;
+}
+
+bool
+TypeCheckContext::lookup_variant_definition (HirId id, HirId *variant)
+{
+ auto it = variants.find (id);
+ if (it == variants.end ())
+ return false;
+
+ *variant = it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_operator_overload (HirId id, TyTy::FnType *call_site)
+{
+ auto it = operator_overloads.find (id);
+ rust_assert (it == operator_overloads.end ());
+
+ operator_overloads[id] = call_site;
+}
+
+bool
+TypeCheckContext::lookup_operator_overload (HirId id, TyTy::FnType **call)
+{
+ auto it = operator_overloads.find (id);
+ if (it == operator_overloads.end ())
+ return false;
+
+ *call = it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_unconstrained_check_marker (HirId id, bool status)
+{
+ unconstrained[id] = status;
+}
+
+bool
+TypeCheckContext::have_checked_for_unconstrained (HirId id, bool *result)
+{
+ auto it = unconstrained.find (id);
+ bool found = it != unconstrained.end ();
+ if (!found)
+ return false;
+
+ *result = it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_resolved_predicate (HirId id,
+ TyTy::TypeBoundPredicate predicate)
+{
+ auto it = predicates.find (id);
+ rust_assert (it == predicates.end ());
+
+ predicates.insert ({id, predicate});
+}
+
+bool
+TypeCheckContext::lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result)
+{
+ auto it = predicates.find (id);
+ bool found = it != predicates.end ();
+ if (!found)
+ return false;
+
+ *result = it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_query (HirId id)
+{
+ querys_in_progress.insert (id);
+}
+
+void
+TypeCheckContext::query_completed (HirId id)
+{
+ querys_in_progress.erase (id);
+}
+
+bool
+TypeCheckContext::query_in_progress (HirId id) const
+{
+ return querys_in_progress.find (id) != querys_in_progress.end ();
+}
+
+void
+TypeCheckContext::insert_trait_query (DefId id)
+{
+ trait_queries_in_progress.insert (id);
+}
+
+void
+TypeCheckContext::trait_query_completed (DefId id)
+{
+ trait_queries_in_progress.erase (id);
+}
+
+bool
+TypeCheckContext::trait_query_in_progress (DefId id) const
+{
+ return trait_queries_in_progress.find (id)
+ != trait_queries_in_progress.end ();
+}
+
+// TypeCheckContextItem
+
+TypeCheckContextItem::Item::Item (HIR::Function *item) : item (item) {}
+
+TypeCheckContextItem::Item::Item (HIR::ImplBlock *impl_block,
+ HIR::Function *item)
+ : impl_item ({impl_block, item})
+{}
+
+TypeCheckContextItem::Item::Item (HIR::TraitItemFunc *trait_item)
+ : trait_item (trait_item)
+{}
+
+TypeCheckContextItem::TypeCheckContextItem (HIR::Function *item)
+ : type (ItemType::ITEM), item (item)
+{}
+
+TypeCheckContextItem::TypeCheckContextItem (HIR::ImplBlock *impl_block,
+ HIR::Function *item)
+ : type (ItemType::IMPL_ITEM), item (impl_block, item)
+{}
+
+TypeCheckContextItem::TypeCheckContextItem (HIR::TraitItemFunc *trait_item)
+ : type (ItemType::TRAIT_ITEM), item (trait_item)
+{}
+
+HIR::Function *
+TypeCheckContextItem::get_item ()
+{
+ rust_assert (get_type () == ItemType::ITEM);
+ return item.item;
+}
+
+std::pair<HIR::ImplBlock *, HIR::Function *> &
+TypeCheckContextItem::get_impl_item ()
+{
+ rust_assert (get_type () == ItemType::IMPL_ITEM);
+ return item.impl_item;
+}
+
+HIR::TraitItemFunc *
+TypeCheckContextItem::get_trait_item ()
+{
+ rust_assert (get_type () == ItemType::TRAIT_ITEM);
+ return item.trait_item;
+}
+
+TypeCheckContextItem::ItemType
+TypeCheckContextItem::get_type () const
+{
+ return type;
+}
+
+TyTy::FnType *
+TypeCheckContextItem::get_context_type ()
+{
+ auto &context = *TypeCheckContext::get ();
+
+ HirId reference = UNKNOWN_HIRID;
+ switch (get_type ())
+ {
+ case ITEM:
+ reference = get_item ()->get_mappings ().get_hirid ();
+ break;
+
+ case IMPL_ITEM:
+ reference = get_impl_item ().second->get_mappings ().get_hirid ();
+ break;
+
+ case TRAIT_ITEM:
+ reference = get_trait_item ()->get_mappings ().get_hirid ();
+ break;
+ }
+
+ rust_assert (reference != UNKNOWN_HIRID);
+
+ TyTy::BaseType *lookup = nullptr;
+ bool ok = context.lookup_type (reference, &lookup);
+ rust_assert (ok);
+ rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
+ return static_cast<TyTy::FnType *> (lookup);
+}
+
+} // namespace Resolver
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index e5057c8..414111c 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -364,6 +364,30 @@ TypeBoundPredicate::lookup_associated_item (const std::string &search) const
return TypeBoundPredicateItem (this, trait_item_ref);
}
+TypeBoundPredicateItem::TypeBoundPredicateItem (
+ const TypeBoundPredicate *parent,
+ const Resolver::TraitItemReference *trait_item_ref)
+ : parent (parent), trait_item_ref (trait_item_ref)
+{}
+
+TypeBoundPredicateItem
+TypeBoundPredicateItem::error ()
+{
+ return TypeBoundPredicateItem (nullptr, nullptr);
+}
+
+bool
+TypeBoundPredicateItem::is_error () const
+{
+ return parent == nullptr || trait_item_ref == nullptr;
+}
+
+const TypeBoundPredicate *
+TypeBoundPredicateItem::get_parent () const
+{
+ return parent;
+}
+
TypeBoundPredicateItem
TypeBoundPredicate::lookup_associated_item (
const Resolver::TraitItemReference *ref) const
@@ -420,7 +444,7 @@ TypeBoundPredicate::is_error () const
BaseType *
TypeBoundPredicate::handle_substitions (
- SubstitutionArgumentMappings subst_mappings)
+ SubstitutionArgumentMappings &subst_mappings)
{
for (auto &sub : get_substs ())
{
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.h b/gcc/rust/typecheck/rust-tyty-bounds.h
new file mode 100644
index 0000000..44839bd
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-bounds.h
@@ -0,0 +1,88 @@
+// 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_TYTY_BOUNDS_H
+#define RUST_TYTY_BOUNDS_H
+
+#include "rust-location.h"
+
+namespace Rust {
+
+namespace Resolver {
+class TraitReference;
+class TraitItemReference;
+class AssociatedImplTrait;
+} // namespace Resolver
+
+namespace TyTy {
+
+class BaseType;
+class TypeBoundPredicate;
+class TypeBoundPredicateItem
+{
+public:
+ TypeBoundPredicateItem (const TypeBoundPredicate *parent,
+ const Resolver::TraitItemReference *trait_item_ref);
+
+ static TypeBoundPredicateItem error ();
+
+ bool is_error () const;
+
+ BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver);
+
+ const Resolver::TraitItemReference *get_raw_item () const;
+
+ bool needs_implementation () const;
+
+ const TypeBoundPredicate *get_parent () const;
+
+ Location get_locus () const;
+
+private:
+ const TypeBoundPredicate *parent;
+ const Resolver::TraitItemReference *trait_item_ref;
+};
+
+class TypeBoundsMappings
+{
+protected:
+ TypeBoundsMappings (std::vector<TypeBoundPredicate> specified_bounds);
+
+public:
+ std::vector<TypeBoundPredicate> &get_specified_bounds ();
+
+ const std::vector<TypeBoundPredicate> &get_specified_bounds () const;
+
+ size_t num_specified_bounds () const;
+
+ std::string raw_bounds_as_string () const;
+
+ std::string bounds_as_string () const;
+
+ std::string raw_bounds_as_name () const;
+
+protected:
+ void add_bound (TypeBoundPredicate predicate);
+
+ std::vector<TypeBoundPredicate> specified_bounds;
+};
+
+} // namespace TyTy
+} // namespace Rust
+
+#endif // RUST_TYTY_BOUNDS_H
diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc
index 6334b69..4010c60 100644
--- a/gcc/rust/typecheck/rust-tyty-call.cc
+++ b/gcc/rust/typecheck/rust-tyty-call.cc
@@ -85,7 +85,6 @@ TypeCheckCallExpr::visit (ADTType &type)
void
TypeCheckCallExpr::visit (FnType &type)
{
- type.monomorphize ();
if (call.num_params () != type.num_params ())
{
if (type.is_varadic ())
@@ -141,8 +140,6 @@ TypeCheckCallExpr::visit (FnType &type)
argument->get_locus ());
if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
{
- rust_error_at (argument->get_locus (),
- "Type Resolution failure on parameter");
return;
}
}
@@ -194,8 +191,6 @@ TypeCheckCallExpr::visit (FnPtr &type)
TyWithLocation (argument_expr_tyty, arg_locus), argument->get_locus ());
if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
{
- rust_error_at (argument->get_locus (),
- "Type Resolution failure on parameter");
return;
}
@@ -302,7 +297,6 @@ TypeCheckMethodCallExpr::check (FnType &type)
TyWithLocation (argument_expr_tyty, arg_locus), arg_locus);
if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
{
- rust_error_at (arg_locus, "Type Resolution failure on parameter");
return new ErrorType (type.get_ref ());
}
diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h
deleted file mode 100644
index dbb808b..0000000
--- a/gcc/rust/typecheck/rust-tyty-rules.h
+++ /dev/null
@@ -1,1406 +0,0 @@
-// 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_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
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc
new file mode 100644
index 0000000..3dfe958
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -0,0 +1,1027 @@
+// 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-tyty-subst.h"
+#include "rust-hir-full.h"
+#include "rust-tyty.h"
+#include "rust-hir-type-check.h"
+#include "rust-substitution-mapper.h"
+#include "rust-hir-type-check-type.h"
+
+namespace Rust {
+namespace TyTy {
+
+SubstitutionParamMapping::SubstitutionParamMapping (
+ const HIR::TypeParam &generic, ParamType *param)
+ : generic (generic), param (param)
+{}
+
+SubstitutionParamMapping::SubstitutionParamMapping (
+ const SubstitutionParamMapping &other)
+ : generic (other.generic), param (other.param)
+{}
+
+std::string
+SubstitutionParamMapping::as_string () const
+{
+ if (param == nullptr)
+ return "nullptr";
+
+ return param->get_name ();
+}
+
+SubstitutionParamMapping
+SubstitutionParamMapping::clone () const
+{
+ return SubstitutionParamMapping (generic,
+ static_cast<ParamType *> (param->clone ()));
+}
+
+ParamType *
+SubstitutionParamMapping::get_param_ty ()
+{
+ return param;
+}
+
+const ParamType *
+SubstitutionParamMapping::get_param_ty () const
+{
+ return param;
+}
+
+const HIR::TypeParam &
+SubstitutionParamMapping::get_generic_param () const
+{
+ return generic;
+}
+
+bool
+SubstitutionParamMapping::needs_substitution () const
+{
+ return !(get_param_ty ()->is_concrete ());
+}
+
+Location
+SubstitutionParamMapping::get_param_locus () const
+{
+ return generic.get_locus ();
+}
+
+bool
+SubstitutionParamMapping::param_has_default_ty () const
+{
+ return generic.has_type ();
+}
+
+BaseType *
+SubstitutionParamMapping::get_default_ty () const
+{
+ TyVar var (generic.get_type_mappings ().get_hirid ());
+ return var.get_tyty ();
+}
+
+bool
+SubstitutionParamMapping::need_substitution () const
+{
+ if (!param->can_resolve ())
+ return true;
+
+ auto resolved = param->resolve ();
+ return !resolved->is_concrete ();
+}
+
+bool
+SubstitutionParamMapping::fill_param_ty (
+ SubstitutionArgumentMappings &subst_mappings, Location locus)
+{
+ SubstitutionArg arg = SubstitutionArg::error ();
+ bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
+ if (!ok)
+ return true;
+
+ TyTy::BaseType &type = *arg.get_tyty ();
+ if (type.get_kind () == TyTy::TypeKind::INFER)
+ {
+ type.inherit_bounds (*param);
+ }
+ else
+ {
+ if (!param->bounds_compatible (type, locus, true))
+ return false;
+ }
+
+ if (type.get_kind () == TypeKind::PARAM)
+ {
+ // delete param;
+ param = static_cast<ParamType *> (type.clone ());
+ }
+ else
+ {
+ // check the substitution is compatible with bounds
+ if (!param->bounds_compatible (type, locus, true))
+ return false;
+
+ // recursively pass this down to all HRTB's
+ for (auto &bound : param->get_specified_bounds ())
+ bound.handle_substitions (subst_mappings);
+
+ param->set_ty_ref (type.get_ref ());
+ subst_mappings.on_param_subst (*param, arg);
+ }
+
+ return true;
+}
+
+void
+SubstitutionParamMapping::override_context ()
+{
+ if (!param->can_resolve ())
+ return;
+
+ auto mappings = Analysis::Mappings::get ();
+ auto context = Resolver::TypeCheckContext::get ();
+
+ context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
+ UNKNOWN_NODEID,
+ param->get_ref (),
+ UNKNOWN_LOCAL_DEFID),
+ param->resolve ());
+}
+
+SubstitutionArg::SubstitutionArg (const SubstitutionParamMapping *param,
+ BaseType *argument)
+ : param (param), argument (argument)
+{}
+
+SubstitutionArg::SubstitutionArg (const SubstitutionArg &other)
+ : param (other.param), argument (other.argument)
+{}
+
+SubstitutionArg &
+SubstitutionArg::operator= (const SubstitutionArg &other)
+{
+ param = other.param;
+ argument = other.argument;
+ return *this;
+}
+
+BaseType *
+SubstitutionArg::get_tyty ()
+{
+ return argument;
+}
+
+const BaseType *
+SubstitutionArg::get_tyty () const
+{
+ return argument;
+}
+
+const SubstitutionParamMapping *
+SubstitutionArg::get_param_mapping () const
+{
+ return param;
+}
+
+SubstitutionArg
+SubstitutionArg::error ()
+{
+ return SubstitutionArg (nullptr, nullptr);
+}
+
+bool
+SubstitutionArg::is_error () const
+{
+ return param == nullptr || argument == nullptr;
+}
+
+bool
+SubstitutionArg::is_conrete () const
+{
+ if (argument == nullptr)
+ return false;
+
+ if (argument->get_kind () == TyTy::TypeKind::PARAM)
+ return false;
+
+ return argument->is_concrete ();
+}
+
+std::string
+SubstitutionArg::as_string () const
+{
+ return param->as_string ()
+ + (argument != nullptr ? ":" + argument->as_string () : "");
+}
+
+// SubstitutionArgumentMappings
+
+SubstitutionArgumentMappings::SubstitutionArgumentMappings (
+ std::vector<SubstitutionArg> mappings,
+ std::map<std::string, BaseType *> binding_args, Location locus,
+ ParamSubstCb param_subst_cb, bool trait_item_flag)
+ : mappings (mappings), binding_args (binding_args), locus (locus),
+ param_subst_cb (param_subst_cb), trait_item_flag (trait_item_flag)
+{}
+
+SubstitutionArgumentMappings::SubstitutionArgumentMappings (
+ const SubstitutionArgumentMappings &other)
+ : mappings (other.mappings), binding_args (other.binding_args),
+ locus (other.locus), param_subst_cb (nullptr),
+ trait_item_flag (other.trait_item_flag)
+{}
+
+SubstitutionArgumentMappings &
+SubstitutionArgumentMappings::operator= (
+ const SubstitutionArgumentMappings &other)
+{
+ mappings = other.mappings;
+ binding_args = other.binding_args;
+ locus = other.locus;
+ param_subst_cb = nullptr;
+ trait_item_flag = other.trait_item_flag;
+
+ return *this;
+}
+
+SubstitutionArgumentMappings
+SubstitutionArgumentMappings::error ()
+{
+ return SubstitutionArgumentMappings ({}, {}, Location (), nullptr, false);
+}
+
+bool
+SubstitutionArgumentMappings::is_error () const
+{
+ return mappings.size () == 0;
+}
+
+bool
+SubstitutionArgumentMappings::get_argument_for_symbol (
+ const ParamType *param_to_find, SubstitutionArg *argument)
+{
+ for (auto &mapping : mappings)
+ {
+ const SubstitutionParamMapping *param = mapping.get_param_mapping ();
+ const ParamType *p = param->get_param_ty ();
+
+ if (p->get_symbol ().compare (param_to_find->get_symbol ()) == 0)
+ {
+ *argument = mapping;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+SubstitutionArgumentMappings::get_argument_at (size_t index,
+ SubstitutionArg *argument)
+{
+ if (index > mappings.size ())
+ return false;
+
+ *argument = mappings.at (index);
+ return true;
+}
+
+bool
+SubstitutionArgumentMappings::is_concrete () const
+{
+ for (auto &mapping : mappings)
+ {
+ if (!mapping.is_conrete ())
+ return false;
+ }
+ return true;
+}
+
+Location
+SubstitutionArgumentMappings::get_locus () const
+{
+ return locus;
+}
+
+size_t
+SubstitutionArgumentMappings::size () const
+{
+ return mappings.size ();
+}
+
+bool
+SubstitutionArgumentMappings::is_empty () const
+{
+ return size () == 0;
+}
+
+std::vector<SubstitutionArg> &
+SubstitutionArgumentMappings::get_mappings ()
+{
+ return mappings;
+}
+
+const std::vector<SubstitutionArg> &
+SubstitutionArgumentMappings::get_mappings () const
+{
+ return mappings;
+}
+
+std::map<std::string, BaseType *> &
+SubstitutionArgumentMappings::get_binding_args ()
+{
+ return binding_args;
+}
+
+const std::map<std::string, BaseType *> &
+SubstitutionArgumentMappings::get_binding_args () const
+{
+ return binding_args;
+}
+
+std::string
+SubstitutionArgumentMappings::as_string () const
+{
+ std::string buffer;
+ for (auto &mapping : mappings)
+ {
+ buffer += mapping.as_string () + ", ";
+ }
+ return "<" + buffer + ">";
+}
+
+void
+SubstitutionArgumentMappings::on_param_subst (const ParamType &p,
+ const SubstitutionArg &a) const
+{
+ if (param_subst_cb == nullptr)
+ return;
+
+ param_subst_cb (p, a);
+}
+
+ParamSubstCb
+SubstitutionArgumentMappings::get_subst_cb () const
+{
+ return param_subst_cb;
+}
+
+bool
+SubstitutionArgumentMappings::trait_item_mode () const
+{
+ return trait_item_flag;
+}
+
+// SubstitutionRef
+
+SubstitutionRef::SubstitutionRef (
+ std::vector<SubstitutionParamMapping> substitutions,
+ SubstitutionArgumentMappings arguments)
+ : substitutions (substitutions), used_arguments (arguments)
+{}
+
+bool
+SubstitutionRef::has_substitutions () const
+{
+ return substitutions.size () > 0;
+}
+
+std::string
+SubstitutionRef::subst_as_string () const
+{
+ std::string buffer;
+ for (size_t i = 0; i < substitutions.size (); i++)
+ {
+ const SubstitutionParamMapping &sub = substitutions.at (i);
+ buffer += sub.as_string ();
+
+ if ((i + 1) < substitutions.size ())
+ buffer += ", ";
+ }
+
+ return buffer.empty () ? "" : "<" + buffer + ">";
+}
+
+bool
+SubstitutionRef::supports_associated_bindings () const
+{
+ return get_num_associated_bindings () > 0;
+}
+
+size_t
+SubstitutionRef::get_num_associated_bindings () const
+{
+ return 0;
+}
+
+TypeBoundPredicateItem
+SubstitutionRef::lookup_associated_type (const std::string &search)
+{
+ return TypeBoundPredicateItem::error ();
+}
+
+size_t
+SubstitutionRef::get_num_substitutions () const
+{
+ return substitutions.size ();
+}
+
+std::vector<SubstitutionParamMapping> &
+SubstitutionRef::get_substs ()
+{
+ return substitutions;
+}
+
+const std::vector<SubstitutionParamMapping> &
+SubstitutionRef::get_substs () const
+{
+ return substitutions;
+}
+
+std::vector<SubstitutionParamMapping>
+SubstitutionRef::clone_substs () const
+{
+ std::vector<SubstitutionParamMapping> clone;
+
+ for (auto &sub : substitutions)
+ clone.push_back (sub.clone ());
+
+ return clone;
+}
+
+void
+SubstitutionRef::override_context ()
+{
+ for (auto &sub : substitutions)
+ {
+ sub.override_context ();
+ }
+}
+
+bool
+SubstitutionRef::needs_substitution () const
+{
+ for (auto &sub : substitutions)
+ {
+ if (sub.need_substitution ())
+ return true;
+ }
+ return false;
+}
+
+bool
+SubstitutionRef::was_substituted () const
+{
+ return !needs_substitution ();
+}
+
+SubstitutionArgumentMappings &
+SubstitutionRef::get_substitution_arguments ()
+{
+ return used_arguments;
+}
+
+const SubstitutionArgumentMappings &
+SubstitutionRef::get_substitution_arguments () const
+{
+ return used_arguments;
+}
+
+size_t
+SubstitutionRef::num_required_substitutions () const
+{
+ size_t n = 0;
+ for (auto &p : substitutions)
+ {
+ if (p.needs_substitution ())
+ n++;
+ }
+ return n;
+}
+
+size_t
+SubstitutionRef::min_required_substitutions () const
+{
+ size_t n = 0;
+ for (auto &p : substitutions)
+ {
+ if (p.needs_substitution () && !p.param_has_default_ty ())
+ n++;
+ }
+ return n;
+}
+
+SubstitutionArgumentMappings
+SubstitutionRef::get_used_arguments () const
+{
+ return used_arguments;
+}
+
+SubstitutionArgumentMappings
+SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args)
+{
+ std::map<std::string, BaseType *> binding_arguments;
+ if (args.get_binding_args ().size () > 0)
+ {
+ if (supports_associated_bindings ())
+ {
+ if (args.get_binding_args ().size () > get_num_associated_bindings ())
+ {
+ RichLocation r (args.get_locus ());
+
+ rust_error_at (r,
+ "generic item takes at most %lu type binding "
+ "arguments but %lu were supplied",
+ (unsigned long) get_num_associated_bindings (),
+ (unsigned long) args.get_binding_args ().size ());
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ for (auto &binding : args.get_binding_args ())
+ {
+ BaseType *resolved
+ = Resolver::TypeCheckType::Resolve (binding.get_type ().get ());
+ if (resolved == nullptr
+ || resolved->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ rust_error_at (binding.get_locus (),
+ "failed to resolve type arguments");
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ // resolve to relevant binding
+ auto binding_item
+ = lookup_associated_type (binding.get_identifier ());
+ if (binding_item.is_error ())
+ {
+ rust_error_at (binding.get_locus (),
+ "unknown associated type binding: %s",
+ binding.get_identifier ().c_str ());
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ binding_arguments[binding.get_identifier ()] = resolved;
+ }
+ }
+ else
+ {
+ RichLocation r (args.get_locus ());
+ for (auto &binding : args.get_binding_args ())
+ r.add_range (binding.get_locus ());
+
+ rust_error_at (r, "associated type bindings are not allowed here");
+ return SubstitutionArgumentMappings::error ();
+ }
+ }
+
+ // for inherited arguments
+ size_t offs = used_arguments.size ();
+ if (args.get_type_args ().size () + offs > substitutions.size ())
+ {
+ RichLocation r (args.get_locus ());
+ r.add_range (substitutions.front ().get_param_locus ());
+
+ rust_error_at (
+ r,
+ "generic item takes at most %lu type arguments but %lu were supplied",
+ (unsigned long) substitutions.size (),
+ (unsigned long) args.get_type_args ().size ());
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ if (args.get_type_args ().size () + offs < min_required_substitutions ())
+ {
+ RichLocation r (args.get_locus ());
+ r.add_range (substitutions.front ().get_param_locus ());
+
+ rust_error_at (
+ r,
+ "generic item takes at least %lu type arguments but %lu were supplied",
+ (unsigned long) (min_required_substitutions () - offs),
+ (unsigned long) args.get_type_args ().size ());
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ std::vector<SubstitutionArg> mappings = used_arguments.get_mappings ();
+ for (auto &arg : args.get_type_args ())
+ {
+ BaseType *resolved = Resolver::TypeCheckType::Resolve (arg.get ());
+ if (resolved == nullptr || resolved->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ rust_error_at (args.get_locus (), "failed to resolve type arguments");
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ SubstitutionArg subst_arg (&substitutions.at (offs), resolved);
+ offs++;
+ mappings.push_back (std::move (subst_arg));
+ }
+
+ // we must need to fill out defaults
+ size_t left_over
+ = num_required_substitutions () - min_required_substitutions ();
+ if (left_over > 0)
+ {
+ for (size_t offs = mappings.size (); offs < substitutions.size (); offs++)
+ {
+ SubstitutionParamMapping &param = substitutions.at (offs);
+ rust_assert (param.param_has_default_ty ());
+
+ BaseType *resolved = param.get_default_ty ();
+ if (resolved->get_kind () == TypeKind::ERROR)
+ return SubstitutionArgumentMappings::error ();
+
+ // this resolved default might already contain default parameters
+ if (resolved->contains_type_parameters ())
+ {
+ SubstitutionArgumentMappings intermediate (mappings,
+ binding_arguments,
+ args.get_locus ());
+ resolved = Resolver::SubstMapperInternal::Resolve (resolved,
+ intermediate);
+
+ if (resolved->get_kind () == TypeKind::ERROR)
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ SubstitutionArg subst_arg (&param, resolved);
+ mappings.push_back (std::move (subst_arg));
+ }
+ }
+
+ return SubstitutionArgumentMappings (mappings, binding_arguments,
+ args.get_locus ());
+}
+
+BaseType *
+SubstitutionRef::infer_substitions (Location locus)
+{
+ std::vector<SubstitutionArg> args;
+ std::map<std::string, BaseType *> argument_mappings;
+ for (auto &p : get_substs ())
+ {
+ if (p.needs_substitution ())
+ {
+ const std::string &symbol = p.get_param_ty ()->get_symbol ();
+ auto it = argument_mappings.find (symbol);
+ bool have_mapping = it != argument_mappings.end ();
+
+ if (have_mapping)
+ {
+ args.push_back (SubstitutionArg (&p, it->second));
+ }
+ else
+ {
+ TyVar infer_var = TyVar::get_implicit_infer_var (locus);
+ args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
+ argument_mappings[symbol] = infer_var.get_tyty ();
+ }
+ }
+ else
+ {
+ args.push_back (SubstitutionArg (&p, p.get_param_ty ()->resolve ()));
+ }
+ }
+
+ // FIXME do we need to add inference variables to all the possible bindings?
+ // it might just lead to inference variable hell not 100% sure if rustc does
+ // this i think the language might needs this to be explicitly set
+
+ SubstitutionArgumentMappings infer_arguments (std::move (args),
+ {} /* binding_arguments */,
+ locus);
+ return handle_substitions (infer_arguments);
+}
+
+SubstitutionArgumentMappings
+SubstitutionRef::adjust_mappings_for_this (
+ SubstitutionArgumentMappings &mappings)
+{
+ std::vector<SubstitutionArg> resolved_mappings;
+ for (size_t i = 0; i < substitutions.size (); i++)
+ {
+ auto &subst = substitutions.at (i);
+
+ SubstitutionArg arg = SubstitutionArg::error ();
+ if (mappings.size () == substitutions.size ())
+ {
+ mappings.get_argument_at (i, &arg);
+ }
+ else
+ {
+ if (subst.needs_substitution ())
+ {
+ // get from passed in mappings
+ mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
+ }
+ else
+ {
+ // we should already have this somewhere
+ used_arguments.get_argument_for_symbol (subst.get_param_ty (),
+ &arg);
+ }
+ }
+
+ bool ok = !arg.is_error ();
+ if (ok)
+ {
+ SubstitutionArg adjusted (&subst, arg.get_tyty ());
+ resolved_mappings.push_back (std::move (adjusted));
+ }
+ }
+
+ if (resolved_mappings.empty ())
+ return SubstitutionArgumentMappings::error ();
+
+ return SubstitutionArgumentMappings (resolved_mappings,
+ mappings.get_binding_args (),
+ mappings.get_locus (),
+ mappings.get_subst_cb (),
+ mappings.trait_item_mode ());
+}
+
+bool
+SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings)
+{
+ std::vector<SubstitutionArg> resolved_mappings;
+ for (size_t i = 0; i < substitutions.size (); i++)
+ {
+ auto &subst = substitutions.at (i);
+
+ SubstitutionArg arg = SubstitutionArg::error ();
+ if (mappings.size () == substitutions.size ())
+ {
+ mappings.get_argument_at (i, &arg);
+ }
+ else
+ {
+ if (subst.needs_substitution ())
+ {
+ // get from passed in mappings
+ mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
+ }
+ else
+ {
+ // we should already have this somewhere
+ used_arguments.get_argument_for_symbol (subst.get_param_ty (),
+ &arg);
+ }
+ }
+
+ bool ok = !arg.is_error ();
+ if (ok)
+ {
+ SubstitutionArg adjusted (&subst, arg.get_tyty ());
+ resolved_mappings.push_back (std::move (adjusted));
+ }
+ }
+
+ return !resolved_mappings.empty ();
+}
+
+// this function assumes that the mappings being passed are for the same type as
+// this new substitution reference so ordering matters here
+SubstitutionArgumentMappings
+SubstitutionRef::solve_mappings_from_receiver_for_self (
+ SubstitutionArgumentMappings &mappings) const
+{
+ std::vector<SubstitutionArg> resolved_mappings;
+
+ rust_assert (mappings.size () == get_num_substitutions ());
+ for (size_t i = 0; i < get_num_substitutions (); i++)
+ {
+ const SubstitutionParamMapping &param_mapping = substitutions.at (i);
+ SubstitutionArg &arg = mappings.get_mappings ().at (i);
+
+ if (param_mapping.needs_substitution ())
+ {
+ SubstitutionArg adjusted (&param_mapping, arg.get_tyty ());
+ resolved_mappings.push_back (std::move (adjusted));
+ }
+ }
+
+ return SubstitutionArgumentMappings (resolved_mappings,
+ mappings.get_binding_args (),
+ mappings.get_locus ());
+}
+
+SubstitutionArgumentMappings
+SubstitutionRef::solve_missing_mappings_from_this (SubstitutionRef &ref,
+ SubstitutionRef &to)
+{
+ rust_assert (!ref.needs_substitution ());
+ rust_assert (needs_substitution ());
+ rust_assert (get_num_substitutions () == ref.get_num_substitutions ());
+
+ Location locus = used_arguments.get_locus ();
+ std::vector<SubstitutionArg> resolved_mappings;
+
+ std::map<HirId, std::pair<ParamType *, BaseType *>> substs;
+ for (size_t i = 0; i < get_num_substitutions (); i++)
+ {
+ SubstitutionParamMapping &a = substitutions.at (i);
+ SubstitutionParamMapping &b = ref.substitutions.at (i);
+
+ if (a.need_substitution ())
+ {
+ const BaseType *root = a.get_param_ty ()->resolve ()->get_root ();
+ rust_assert (root->get_kind () == TyTy::TypeKind::PARAM);
+ const ParamType *p = static_cast<const TyTy::ParamType *> (root);
+
+ substs[p->get_ty_ref ()] = {static_cast<ParamType *> (p->clone ()),
+ b.get_param_ty ()->resolve ()};
+ }
+ }
+
+ for (auto it = substs.begin (); it != substs.end (); it++)
+ {
+ HirId param_id = it->first;
+ BaseType *arg = it->second.second;
+
+ const SubstitutionParamMapping *associate_param = nullptr;
+ for (SubstitutionParamMapping &p : to.substitutions)
+ {
+ if (p.get_param_ty ()->get_ty_ref () == param_id)
+ {
+ associate_param = &p;
+ break;
+ }
+ }
+
+ rust_assert (associate_param != nullptr);
+ SubstitutionArg argument (associate_param, arg);
+ resolved_mappings.push_back (std::move (argument));
+ }
+
+ return SubstitutionArgumentMappings (resolved_mappings, {}, locus);
+}
+
+bool
+SubstitutionRef::monomorphize ()
+{
+ auto context = Resolver::TypeCheckContext::get ();
+ for (const auto &subst : get_substs ())
+ {
+ const TyTy::ParamType *pty = subst.get_param_ty ();
+
+ if (!pty->can_resolve ())
+ continue;
+
+ const TyTy::BaseType *binding = pty->resolve ();
+ if (binding->get_kind () == TyTy::TypeKind::PARAM)
+ continue;
+
+ for (const auto &bound : pty->get_specified_bounds ())
+ {
+ const Resolver::TraitReference *specified_bound_ref = bound.get ();
+
+ // setup any associated type mappings for the specified bonds and this
+ // type
+ auto candidates = Resolver::TypeBoundsProbe::Probe (binding);
+ std::vector<Resolver::AssociatedImplTrait *> associated_impl_traits;
+ for (auto &probed_bound : candidates)
+ {
+ const Resolver::TraitReference *bound_trait_ref
+ = probed_bound.first;
+ const HIR::ImplBlock *associated_impl = probed_bound.second;
+
+ HirId impl_block_id
+ = associated_impl->get_mappings ().get_hirid ();
+ Resolver::AssociatedImplTrait *associated = nullptr;
+ bool found_impl_trait
+ = context->lookup_associated_trait_impl (impl_block_id,
+ &associated);
+ if (found_impl_trait)
+ {
+ bool found_trait
+ = specified_bound_ref->is_equal (*bound_trait_ref);
+ bool found_self
+ = associated->get_self ()->can_eq (binding, false);
+ if (found_trait && found_self)
+ {
+ associated_impl_traits.push_back (associated);
+ }
+ }
+ }
+
+ if (!associated_impl_traits.empty ())
+ {
+ // This code is important when you look at slices for example when
+ // you have a slice such as:
+ //
+ // let slice = &array[1..3]
+ //
+ // the higher ranked bounds will end up having an Index trait
+ // implementation for Range<usize> so we need this code to resolve
+ // that we have an integer inference variable that needs to become
+ // a usize
+ //
+ // The other complicated issue is that we might have an intrinsic
+ // which requires the :Clone or Copy bound but the libcore adds
+ // implementations for all the integral types so when there are
+ // multiple candidates we need to resolve to the default
+ // implementation for that type otherwise its an error for
+ // ambiguous type bounds
+
+ if (associated_impl_traits.size () == 1)
+ {
+ Resolver::AssociatedImplTrait *associate_impl_trait
+ = associated_impl_traits.at (0);
+ associate_impl_trait->setup_associated_types (binding, bound);
+ }
+ else
+ {
+ // if we have a non-general inference variable we need to be
+ // careful about the selection here
+ bool is_infer_var
+ = binding->get_kind () == TyTy::TypeKind::INFER;
+ bool is_integer_infervar
+ = is_infer_var
+ && static_cast<const TyTy::InferType *> (binding)
+ ->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::INTEGRAL;
+ bool is_float_infervar
+ = is_infer_var
+ && static_cast<const TyTy::InferType *> (binding)
+ ->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::FLOAT;
+
+ Resolver::AssociatedImplTrait *associate_impl_trait = nullptr;
+ if (is_integer_infervar)
+ {
+ TyTy::BaseType *type = nullptr;
+ bool ok = context->lookup_builtin ("i32", &type);
+ rust_assert (ok);
+
+ for (auto &impl : associated_impl_traits)
+ {
+ bool found = impl->get_self ()->is_equal (*type);
+ if (found)
+ {
+ associate_impl_trait = impl;
+ break;
+ }
+ }
+ }
+ else if (is_float_infervar)
+ {
+ TyTy::BaseType *type = nullptr;
+ bool ok = context->lookup_builtin ("f64", &type);
+ rust_assert (ok);
+
+ for (auto &impl : associated_impl_traits)
+ {
+ bool found = impl->get_self ()->is_equal (*type);
+ if (found)
+ {
+ associate_impl_trait = impl;
+ break;
+ }
+ }
+ }
+
+ if (associate_impl_trait == nullptr)
+ {
+ // go for the first one? or error out?
+ auto &mappings = *Analysis::Mappings::get ();
+ const auto &type_param = subst.get_generic_param ();
+ const auto *trait_ref = bound.get ();
+
+ RichLocation r (type_param.get_locus ());
+ r.add_range (bound.get_locus ());
+ r.add_range (
+ mappings.lookup_location (binding->get_ref ()));
+
+ rust_error_at (
+ r, "ambiguous type bound for trait %s and type %s",
+ trait_ref->get_name ().c_str (),
+ binding->get_name ().c_str ());
+
+ return false;
+ }
+
+ associate_impl_trait->setup_associated_types (binding, bound);
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+} // namespace TyTy
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h
new file mode 100644
index 0000000..982861e
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-subst.h
@@ -0,0 +1,317 @@
+// 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_TYTY_SUBST_H
+#define RUST_TYTY_SUBST_H
+
+#include "rust-system.h"
+#include "rust-location.h"
+#include "rust-hir-full-decls.h"
+#include "rust-tyty-bounds.h"
+
+namespace Rust {
+namespace TyTy {
+
+class BaseType;
+class ParamType;
+class SubstitutionArgumentMappings;
+class SubstitutionParamMapping
+{
+public:
+ SubstitutionParamMapping (const HIR::TypeParam &generic, ParamType *param);
+
+ SubstitutionParamMapping (const SubstitutionParamMapping &other);
+
+ std::string as_string () const;
+
+ bool fill_param_ty (SubstitutionArgumentMappings &subst_mappings,
+ Location locus);
+
+ SubstitutionParamMapping clone () const;
+
+ ParamType *get_param_ty ();
+
+ const ParamType *get_param_ty () const;
+
+ const HIR::TypeParam &get_generic_param () const;
+
+ // this is used for the backend to override the HirId ref of the param to
+ // what the concrete type is for the rest of the context
+ void override_context ();
+
+ bool needs_substitution () const;
+
+ Location get_param_locus () const;
+
+ bool param_has_default_ty () const;
+
+ BaseType *get_default_ty () const;
+
+ bool need_substitution () const;
+
+private:
+ const HIR::TypeParam &generic;
+ ParamType *param;
+};
+
+class SubstitutionArg
+{
+public:
+ SubstitutionArg (const SubstitutionParamMapping *param, BaseType *argument);
+
+ // FIXME
+ // the copy constructors need removed - they are unsafe see
+ // TypeBoundPredicate
+ SubstitutionArg (const SubstitutionArg &other);
+
+ SubstitutionArg &operator= (const SubstitutionArg &other);
+
+ BaseType *get_tyty ();
+
+ const BaseType *get_tyty () const;
+
+ const SubstitutionParamMapping *get_param_mapping () const;
+
+ static SubstitutionArg error ();
+
+ bool is_error () const;
+
+ bool is_conrete () const;
+
+ std::string as_string () const;
+
+private:
+ const SubstitutionParamMapping *param;
+ BaseType *argument;
+};
+
+typedef std::function<void (const ParamType &, const SubstitutionArg &)>
+ ParamSubstCb;
+class SubstitutionArgumentMappings
+{
+public:
+ SubstitutionArgumentMappings (std::vector<SubstitutionArg> mappings,
+ std::map<std::string, BaseType *> binding_args,
+ Location locus,
+ ParamSubstCb param_subst_cb = nullptr,
+ bool trait_item_flag = false);
+
+ SubstitutionArgumentMappings (const SubstitutionArgumentMappings &other);
+ SubstitutionArgumentMappings &
+ operator= (const SubstitutionArgumentMappings &other);
+
+ SubstitutionArgumentMappings (SubstitutionArgumentMappings &&other) = default;
+ SubstitutionArgumentMappings &operator= (SubstitutionArgumentMappings &&other)
+ = default;
+
+ static SubstitutionArgumentMappings error ();
+
+ bool is_error () const;
+
+ bool get_argument_for_symbol (const ParamType *param_to_find,
+ SubstitutionArg *argument);
+
+ bool get_argument_at (size_t index, SubstitutionArg *argument);
+
+ // is_concrete means if the used args is non error, ie: non empty this will
+ // verify if actual real types have been put in place of are they still
+ // ParamTy
+ bool is_concrete () const;
+
+ Location get_locus () const;
+
+ size_t size () const;
+
+ bool is_empty () const;
+
+ std::vector<SubstitutionArg> &get_mappings ();
+
+ const std::vector<SubstitutionArg> &get_mappings () const;
+
+ std::map<std::string, BaseType *> &get_binding_args ();
+
+ const std::map<std::string, BaseType *> &get_binding_args () const;
+
+ std::string as_string () const;
+
+ void on_param_subst (const ParamType &p, const SubstitutionArg &a) const;
+
+ ParamSubstCb get_subst_cb () const;
+
+ bool trait_item_mode () const;
+
+private:
+ std::vector<SubstitutionArg> mappings;
+ std::map<std::string, BaseType *> binding_args;
+ Location locus;
+ ParamSubstCb param_subst_cb;
+ bool trait_item_flag;
+};
+
+class SubstitutionRef
+{
+public:
+ SubstitutionRef (std::vector<SubstitutionParamMapping> substitutions,
+ SubstitutionArgumentMappings arguments);
+
+ bool has_substitutions () const;
+
+ std::string subst_as_string () const;
+
+ bool supports_associated_bindings () const;
+
+ // this is overridden in TypeBoundPredicate
+ // which support bindings we don't add them directly to the SubstitutionRef
+ // base class because this class represents the fn<X: Foo, Y: Bar>. The only
+ // construct which supports associated types
+ virtual size_t get_num_associated_bindings () const;
+
+ // this is overridden in TypeBoundPredicate
+ virtual TypeBoundPredicateItem
+ lookup_associated_type (const std::string &search);
+
+ size_t get_num_substitutions () const;
+
+ std::vector<SubstitutionParamMapping> &get_substs ();
+
+ const std::vector<SubstitutionParamMapping> &get_substs () const;
+
+ std::vector<SubstitutionParamMapping> clone_substs () const;
+
+ void override_context ();
+
+ bool needs_substitution () const;
+
+ bool was_substituted () const;
+
+ SubstitutionArgumentMappings &get_substitution_arguments ();
+ const SubstitutionArgumentMappings &get_substitution_arguments () const;
+
+ // this is the count of type params that are not substituted fuly
+ size_t num_required_substitutions () const;
+
+ // this is the count of type params that need substituted taking into account
+ // possible defaults
+ size_t min_required_substitutions () const;
+
+ // We are trying to subst <i32, f32> into Struct Foo<X,Y> {}
+ // in the case of Foo<i32,f32>{...}
+ //
+ // the substitions we have here define X,Y but the arguments have no bindings
+ // so its a matter of ordering
+ SubstitutionArgumentMappings
+ get_mappings_from_generic_args (HIR::GenericArgs &args);
+
+ // Recursive substitutions
+ // Foo <A,B> { a:A, b: B}; Bar <X,Y,Z>{a:X, b: Foo<Y,Z>}
+ //
+ // we have bindings for X Y Z and need to propagate the binding Y,Z into Foo
+ // Which binds to A,B
+ SubstitutionArgumentMappings
+ adjust_mappings_for_this (SubstitutionArgumentMappings &mappings);
+
+ // Are the mappings here actually bound to this type. For example imagine the
+ // case:
+ //
+ // struct Foo<T>(T);
+ // impl<T> Foo<T> {
+ // fn test(self) { ... }
+ // }
+ //
+ // In this case we have a generic ADT of Foo and an impl block of a generic T
+ // on Foo for the Self type. When we it comes to path resolution we can have:
+ //
+ // Foo::<i32>::test()
+ //
+ // This means the first segment of Foo::<i32> returns the ADT Foo<i32> not the
+ // Self ADT bound to the T from the impl block. This means when it comes to
+ // the next segment of test which resolves to the function we need to check
+ // wether the arguments in the struct definition of foo can be bound here
+ // before substituting the previous segments type here. This functions acts as
+ // a guard for the solve_mappings_from_receiver_for_self to handle the case
+ // where arguments are not bound. This is important for this next case:
+ //
+ // struct Baz<A, B>(A, B);
+ // impl Baz<i32, f32> {
+ // fn test<X>(a: X) -> X {
+ // a
+ // }
+ // }
+ //
+ // In this case Baz has been already substituted for the impl's Self to become
+ // ADT<i32, f32> so that the function test only has 1 generic argument of X.
+ // The path for this will be:
+ //
+ // Baz::test::<_>(123)
+ //
+ // So the first segment here will be Baz<_, _> to try and infer the arguments
+ // which will be taken from the impl's Self type in this case since it is
+ // already substituted and like the previous case the check to see if we need
+ // to inherit the previous segments generic arguments takes place but the
+ // generic arguments are not bound to this type as they have already been
+ // substituted.
+ //
+ // Its important to remember from the first example the FnType actually looks
+ // like:
+ //
+ // fn <T>test(self :Foo<T>(T))
+ //
+ // As the generic parameters are "bound" to each of the items in the impl
+ // block. So this check is about wether the arguments we have here can
+ // actually be bound to this type.
+ bool are_mappings_bound (SubstitutionArgumentMappings &mappings);
+
+ // struct Foo<A, B>(A, B);
+ //
+ // impl<T> Foo<T, f32>;
+ // -> fn test<X>(self, a: X) -> X
+ //
+ // We might invoke this via:
+ //
+ // a = Foo(123, 456f32);
+ // b = a.test::<bool>(false);
+ //
+ // we need to figure out relevant generic arguemts for self to apply to the
+ // fntype
+ SubstitutionArgumentMappings solve_mappings_from_receiver_for_self (
+ SubstitutionArgumentMappings &mappings) const;
+
+ // TODO comment
+ SubstitutionArgumentMappings
+ solve_missing_mappings_from_this (SubstitutionRef &ref, SubstitutionRef &to);
+
+ // TODO comment
+ BaseType *infer_substitions (Location locus);
+
+ // TODO comment
+ bool monomorphize ();
+
+ // TODO comment
+ virtual BaseType *handle_substitions (SubstitutionArgumentMappings &mappings)
+ = 0;
+
+ SubstitutionArgumentMappings get_used_arguments () const;
+
+protected:
+ std::vector<SubstitutionParamMapping> substitutions;
+ SubstitutionArgumentMappings used_arguments;
+};
+
+} // namespace TyTy
+} // namespace Rust
+#endif // RUST_TYTY_SUBST_H
diff --git a/gcc/rust/typecheck/rust-tyty-util.cc b/gcc/rust/typecheck/rust-tyty-util.cc
new file mode 100644
index 0000000..5037f68
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-util.cc
@@ -0,0 +1,116 @@
+// 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-hir-type-check.h"
+#include "rust-tyty.h"
+
+namespace Rust {
+namespace TyTy {
+
+TyVar::TyVar (HirId ref) : ref (ref)
+{
+ // ensure this reference is defined within the context
+ auto context = Resolver::TypeCheckContext::get ();
+ BaseType *lookup = nullptr;
+ bool ok = context->lookup_type (ref, &lookup);
+ rust_assert (ok);
+}
+
+BaseType *
+TyVar::get_tyty () const
+{
+ auto context = Resolver::TypeCheckContext::get ();
+ BaseType *lookup = nullptr;
+ bool ok = context->lookup_type (ref, &lookup);
+ rust_assert (ok);
+ return lookup;
+}
+
+TyVar
+TyVar::get_implicit_infer_var (Location locus)
+{
+ auto mappings = Analysis::Mappings::get ();
+ auto context = Resolver::TypeCheckContext::get ();
+
+ InferType *infer = new InferType (mappings->get_next_hir_id (),
+ InferType::InferTypeKind::GENERAL, locus);
+ context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
+ UNKNOWN_NODEID,
+ infer->get_ref (),
+ UNKNOWN_LOCAL_DEFID),
+ infer);
+ mappings->insert_location (infer->get_ref (), locus);
+
+ return TyVar (infer->get_ref ());
+}
+
+TyVar
+TyVar::subst_covariant_var (TyTy::BaseType *orig, TyTy::BaseType *subst)
+{
+ if (orig->get_kind () != TyTy::TypeKind::PARAM)
+ return TyVar (subst->get_ty_ref ());
+ else if (subst->get_kind () == TyTy::TypeKind::PARAM)
+ {
+ TyTy::ParamType *p = static_cast<TyTy::ParamType *> (subst);
+ if (p->resolve ()->get_kind () == TyTy::TypeKind::PARAM)
+ {
+ return TyVar (subst->get_ty_ref ());
+ }
+ }
+
+ return TyVar (subst->get_ref ());
+}
+
+TyVar
+TyVar::clone () const
+{
+ TyTy::BaseType *c = get_tyty ()->clone ();
+ return TyVar (c->get_ref ());
+}
+
+TyVar
+TyVar::monomorphized_clone () const
+{
+ auto mappings = Analysis::Mappings::get ();
+ auto context = Resolver::TypeCheckContext::get ();
+
+ // this needs a new hirid
+ TyTy::BaseType *c = get_tyty ()->monomorphized_clone ();
+ c->set_ref (mappings->get_next_hir_id ());
+
+ // insert it
+ context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
+ UNKNOWN_NODEID, c->get_ref (),
+ UNKNOWN_LOCAL_DEFID),
+ c);
+
+ return TyVar (c->get_ref ());
+}
+
+TyWithLocation::TyWithLocation (BaseType *ty, Location locus)
+ : ty (ty), locus (locus)
+{}
+
+TyWithLocation::TyWithLocation (BaseType *ty) : ty (ty)
+{
+ auto mappings = Analysis::Mappings::get ();
+ locus = mappings->lookup_location (ty->get_ref ());
+}
+
+} // namespace TyTy
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-util.h b/gcc/rust/typecheck/rust-tyty-util.h
new file mode 100644
index 0000000..eccbb44
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-util.h
@@ -0,0 +1,69 @@
+// 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_TYTY_UTIL_H
+#define RUST_TYTY_UTIL_H
+
+#include "rust-hir-map.h"
+
+namespace Rust {
+namespace TyTy {
+
+class BaseType;
+
+// this is a placeholder for types that can change like inference variables
+class TyVar
+{
+public:
+ explicit TyVar (HirId ref);
+
+ HirId get_ref () const { return ref; }
+
+ BaseType *get_tyty () const;
+
+ TyVar clone () const;
+
+ TyVar monomorphized_clone () const;
+
+ static TyVar get_implicit_infer_var (Location locus);
+
+ static TyVar subst_covariant_var (TyTy::BaseType *orig,
+ TyTy::BaseType *subst);
+
+private:
+ HirId ref;
+};
+
+class TyWithLocation
+{
+public:
+ explicit TyWithLocation (BaseType *ty, Location locus);
+ explicit TyWithLocation (BaseType *ty);
+
+ BaseType *get_ty () const { return ty; }
+ Location get_locus () const { return locus; }
+
+private:
+ BaseType *ty;
+ Location locus;
+};
+
+} // namespace TyTy
+} // namespace Rust
+
+#endif // RUST_TYTY_UTIL_H
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 9358919..8c3bed4 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -17,17 +17,21 @@
// <http://www.gnu.org/licenses/>.
#include "rust-tyty.h"
-#include "rust-tyty-visitor.h"
-#include "rust-tyty-call.h"
+
#include "rust-hir-type-check-expr.h"
#include "rust-hir-type-check-type.h"
-#include "rust-tyty-rules.h"
-#include "rust-tyty-cmp.h"
+#include "rust-tyty-visitor.h"
+#include "rust-tyty-call.h"
#include "rust-hir-map.h"
+#include "rust-location.h"
+#include "rust-linemap.h"
+
#include "rust-substitution-mapper.h"
-#include "rust-hir-trait-ref.h"
+#include "rust-hir-trait-reference.h"
#include "rust-hir-type-bounds.h"
#include "rust-hir-trait-resolve.h"
+#include "rust-tyty-cmp.h"
+
#include "options.h"
namespace Rust {
@@ -146,6 +150,122 @@ is_primitive_type_kind (TypeKind kind)
}
}
+// BASE TYPE
+
+BaseType::BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
+ std::set<HirId> refs)
+ : TypeBoundsMappings ({}), kind (kind), ref (ref), ty_ref (ty_ref),
+ combined (refs), ident (ident), mappings (Analysis::Mappings::get ())
+{}
+
+BaseType::BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
+ std::vector<TypeBoundPredicate> specified_bounds,
+ std::set<HirId> refs)
+ : TypeBoundsMappings (specified_bounds), kind (kind), ref (ref),
+ ty_ref (ty_ref), combined (refs), ident (ident),
+ mappings (Analysis::Mappings::get ())
+{}
+
+BaseType::~BaseType () {}
+
+HirId
+BaseType::get_ref () const
+{
+ return ref;
+}
+
+void
+BaseType::set_ref (HirId id)
+{
+ if (id != ref)
+ append_reference (ref);
+ ref = id;
+}
+
+HirId
+BaseType::get_ty_ref () const
+{
+ return ty_ref;
+}
+
+void
+BaseType::set_ty_ref (HirId id)
+{
+ ty_ref = id;
+}
+
+bool
+BaseType::is_equal (const BaseType &other) const
+{
+ return get_kind () == other.get_kind ();
+}
+
+bool
+BaseType::is_unit () const
+{
+ return false;
+}
+
+TypeKind
+BaseType::get_kind () const
+{
+ return kind;
+}
+
+std::set<HirId>
+BaseType::get_combined_refs () const
+{
+ return combined;
+}
+
+void
+BaseType::append_reference (HirId id)
+{
+ combined.insert (id);
+}
+
+bool
+BaseType::supports_substitutions () const
+{
+ return false;
+}
+
+bool
+BaseType::has_subsititions_defined () const
+{
+ return false;
+}
+
+bool
+BaseType::can_substitute () const
+{
+ return supports_substitutions () && has_subsititions_defined ();
+}
+
+bool
+BaseType::needs_generic_substitutions () const
+{
+ return false;
+}
+
+bool
+BaseType::contains_type_parameters () const
+{
+ return !is_concrete ();
+}
+
+const RustIdent &
+BaseType::get_ident () const
+{
+ return ident;
+}
+
+Location
+BaseType::get_locus () const
+{
+ return ident.locus;
+}
+
bool
BaseType::satisfies_bound (const TypeBoundPredicate &predicate) const
{
@@ -255,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
{
@@ -276,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;
@@ -330,94 +508,38 @@ BaseType::debug () const
debug_str ().c_str ());
}
-TyVar::TyVar (HirId ref) : ref (ref)
-{
- // ensure this reference is defined within the context
- auto context = Resolver::TypeCheckContext::get ();
- BaseType *lookup = nullptr;
- bool ok = context->lookup_type (ref, &lookup);
- rust_assert (ok);
-}
-
-BaseType *
-TyVar::get_tyty () const
-{
- auto context = Resolver::TypeCheckContext::get ();
- BaseType *lookup = nullptr;
- bool ok = context->lookup_type (ref, &lookup);
- rust_assert (ok);
- return lookup;
-}
-
-TyVar
-TyVar::get_implicit_infer_var (Location locus)
-{
- auto mappings = Analysis::Mappings::get ();
- auto context = Resolver::TypeCheckContext::get ();
+// InferType
- InferType *infer = new InferType (mappings->get_next_hir_id (),
- InferType::InferTypeKind::GENERAL, locus);
- context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
- UNKNOWN_NODEID,
- infer->get_ref (),
- UNKNOWN_LOCAL_DEFID),
- infer);
- mappings->insert_location (infer->get_ref (), locus);
+InferType::InferType (HirId ref, InferTypeKind infer_kind, Location locus,
+ std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::INFER,
+ {Resolver::CanonicalPath::create_empty (), locus}, refs),
+ infer_kind (infer_kind)
+{}
- return TyVar (infer->get_ref ());
-}
+InferType::InferType (HirId ref, HirId ty_ref, InferTypeKind infer_kind,
+ Location locus, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::INFER,
+ {Resolver::CanonicalPath::create_empty (), locus}, refs),
+ infer_kind (infer_kind)
+{}
-TyVar
-TyVar::subst_covariant_var (TyTy::BaseType *orig, TyTy::BaseType *subst)
+InferType::InferTypeKind
+InferType::get_infer_kind () const
{
- if (orig->get_kind () != TyTy::TypeKind::PARAM)
- return TyVar (subst->get_ty_ref ());
- else if (subst->get_kind () == TyTy::TypeKind::PARAM)
- {
- TyTy::ParamType *p = static_cast<TyTy::ParamType *> (subst);
- if (p->resolve ()->get_kind () == TyTy::TypeKind::PARAM)
- {
- return TyVar (subst->get_ty_ref ());
- }
- }
-
- return TyVar (subst->get_ref ());
+ return infer_kind;
}
-TyVar
-TyVar::clone () const
+std::string
+InferType::get_name () const
{
- TyTy::BaseType *c = get_tyty ()->clone ();
- return TyVar (c->get_ref ());
+ return as_string ();
}
-TyVar
-TyVar::monomorphized_clone () const
-{
- auto mappings = Analysis::Mappings::get ();
- auto context = Resolver::TypeCheckContext::get ();
-
- // this needs a new hirid
- TyTy::BaseType *c = get_tyty ()->monomorphized_clone ();
- c->set_ref (mappings->get_next_hir_id ());
-
- // insert it
- context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
- UNKNOWN_NODEID, c->get_ref (),
- UNKNOWN_LOCAL_DEFID),
- c);
-
- return TyVar (c->get_ref ());
-}
-
-TyWithLocation::TyWithLocation (BaseType *ty, Location locus)
- : ty (ty), locus (locus)
-{}
-
-TyWithLocation::TyWithLocation (BaseType *ty) : ty (ty)
+bool
+InferType::is_concrete () const
{
- auto mappings = Analysis::Mappings::get ();
- locus = mappings->lookup_location (ty->get_ref ());
+ return true;
}
void
@@ -447,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
{
@@ -525,6 +640,35 @@ InferType::default_type (BaseType **type) const
return false;
}
+// ErrorType
+
+ErrorType::ErrorType (HirId ref, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::ERROR,
+ {Resolver::CanonicalPath::create_empty (), Location ()}, refs)
+{}
+
+ErrorType::ErrorType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::ERROR,
+ {Resolver::CanonicalPath::create_empty (), Location ()}, refs)
+{}
+
+bool
+ErrorType::is_unit () const
+{
+ return true;
+}
+bool
+ErrorType::is_concrete () const
+{
+ return false;
+}
+
+std::string
+ErrorType::get_name () const
+{
+ return as_string ();
+}
+
void
ErrorType::accept_vis (TyVisitor &vis)
{
@@ -543,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
{
@@ -567,6 +705,55 @@ ErrorType::monomorphized_clone () const
return clone ();
}
+// Struct Field type
+
+StructFieldType::StructFieldType (HirId ref, std::string name, BaseType *ty,
+ Location locus)
+ : ref (ref), name (name), ty (ty), locus (locus)
+{}
+
+HirId
+StructFieldType::get_ref () const
+{
+ return ref;
+}
+
+std::string
+StructFieldType::get_name () const
+{
+ return name;
+}
+
+BaseType *
+StructFieldType::get_field_type () const
+{
+ return ty;
+}
+
+void
+StructFieldType::set_field_type (BaseType *fty)
+{
+ ty = fty;
+}
+
+bool
+StructFieldType::is_concrete () const
+{
+ return ty->is_concrete ();
+}
+
+void
+StructFieldType::debug () const
+{
+ rust_debug ("%s", as_string ().c_str ());
+}
+
+Location
+StructFieldType::get_locus () const
+{
+ return locus;
+}
+
std::string
StructFieldType::as_string () const
{
@@ -604,472 +791,241 @@ StructFieldType::monomorphized_clone () const
get_field_type ()->monomorphized_clone (), locus);
}
-bool
-SubstitutionParamMapping::need_substitution () const
-{
- if (!param->can_resolve ())
- return true;
+// VariantDef
- auto resolved = param->resolve ();
- return !resolved->is_concrete ();
-}
-
-bool
-SubstitutionParamMapping::fill_param_ty (
- SubstitutionArgumentMappings &subst_mappings, Location locus)
+std::string
+VariantDef::variant_type_string (VariantType type)
{
- SubstitutionArg arg = SubstitutionArg::error ();
- bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
- if (!ok)
- return true;
-
- TyTy::BaseType &type = *arg.get_tyty ();
- if (type.get_kind () == TyTy::TypeKind::INFER)
- {
- type.inherit_bounds (*param);
- }
- else
+ switch (type)
{
- if (!param->bounds_compatible (type, locus, true))
- return false;
- }
-
- if (type.get_kind () == TypeKind::PARAM)
- {
- // delete param;
- param = static_cast<ParamType *> (type.clone ());
+ case NUM:
+ return "enumeral";
+ case TUPLE:
+ return "tuple";
+ case STRUCT:
+ return "struct";
}
- else
- {
- // check the substitution is compatible with bounds
- if (!param->bounds_compatible (type, locus, true))
- return false;
-
- // recursively pass this down to all HRTB's
- for (auto &bound : param->get_specified_bounds ())
- bound.handle_substitions (subst_mappings);
-
- param->set_ty_ref (type.get_ref ());
- }
-
- return true;
+ gcc_unreachable ();
+ return "";
}
-void
-SubstitutionParamMapping::override_context ()
-{
- if (!param->can_resolve ())
- return;
+VariantDef::VariantDef (HirId id, DefId defid, std::string identifier,
+ RustIdent ident, HIR::Expr *discriminant)
+ : id (id), defid (defid), identifier (identifier), ident (ident),
+ discriminant (discriminant)
- auto mappings = Analysis::Mappings::get ();
- auto context = Resolver::TypeCheckContext::get ();
-
- context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
- UNKNOWN_NODEID,
- param->get_ref (),
- UNKNOWN_LOCAL_DEFID),
- param->resolve ());
+{
+ type = VariantType::NUM;
+ fields = {};
}
-SubstitutionArgumentMappings
-SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args)
+VariantDef::VariantDef (HirId id, DefId defid, std::string identifier,
+ RustIdent ident, VariantType type,
+ HIR::Expr *discriminant,
+ std::vector<StructFieldType *> fields)
+ : id (id), defid (defid), identifier (identifier), ident (ident), type (type),
+ discriminant (discriminant), fields (fields)
{
- std::map<std::string, BaseType *> binding_arguments;
- if (args.get_binding_args ().size () > 0)
- {
- if (supports_associated_bindings ())
- {
- if (args.get_binding_args ().size () > get_num_associated_bindings ())
- {
- RichLocation r (args.get_locus ());
-
- rust_error_at (r,
- "generic item takes at most %lu type binding "
- "arguments but %lu were supplied",
- (unsigned long) get_num_associated_bindings (),
- (unsigned long) args.get_binding_args ().size ());
- return SubstitutionArgumentMappings::error ();
- }
-
- for (auto &binding : args.get_binding_args ())
- {
- BaseType *resolved
- = Resolver::TypeCheckType::Resolve (binding.get_type ().get ());
- if (resolved == nullptr
- || resolved->get_kind () == TyTy::TypeKind::ERROR)
- {
- rust_error_at (binding.get_locus (),
- "failed to resolve type arguments");
- return SubstitutionArgumentMappings::error ();
- }
-
- // resolve to relevant binding
- auto binding_item
- = lookup_associated_type (binding.get_identifier ());
- if (binding_item.is_error ())
- {
- rust_error_at (binding.get_locus (),
- "unknown associated type binding: %s",
- binding.get_identifier ().c_str ());
- return SubstitutionArgumentMappings::error ();
- }
-
- binding_arguments[binding.get_identifier ()] = resolved;
- }
- }
- else
- {
- RichLocation r (args.get_locus ());
- for (auto &binding : args.get_binding_args ())
- r.add_range (binding.get_locus ());
-
- rust_error_at (r, "associated type bindings are not allowed here");
- return SubstitutionArgumentMappings::error ();
- }
- }
-
- // for inherited arguments
- size_t offs = used_arguments.size ();
- if (args.get_type_args ().size () + offs > substitutions.size ())
- {
- RichLocation r (args.get_locus ());
- r.add_range (substitutions.front ().get_param_locus ());
-
- rust_error_at (
- r,
- "generic item takes at most %lu type arguments but %lu were supplied",
- (unsigned long) substitutions.size (),
- (unsigned long) args.get_type_args ().size ());
- return SubstitutionArgumentMappings::error ();
- }
-
- if (args.get_type_args ().size () + offs < min_required_substitutions ())
- {
- RichLocation r (args.get_locus ());
- r.add_range (substitutions.front ().get_param_locus ());
-
- rust_error_at (
- r,
- "generic item takes at least %lu type arguments but %lu were supplied",
- (unsigned long) (min_required_substitutions () - offs),
- (unsigned long) args.get_type_args ().size ());
- return SubstitutionArgumentMappings::error ();
- }
-
- std::vector<SubstitutionArg> mappings = used_arguments.get_mappings ();
- for (auto &arg : args.get_type_args ())
- {
- BaseType *resolved = Resolver::TypeCheckType::Resolve (arg.get ());
- if (resolved == nullptr || resolved->get_kind () == TyTy::TypeKind::ERROR)
- {
- rust_error_at (args.get_locus (), "failed to resolve type arguments");
- return SubstitutionArgumentMappings::error ();
- }
+ rust_assert ((type == VariantType::NUM && fields.empty ())
+ || (type == VariantType::TUPLE || type == VariantType::STRUCT));
+}
- SubstitutionArg subst_arg (&substitutions.at (offs), resolved);
- offs++;
- mappings.push_back (std::move (subst_arg));
- }
+VariantDef::VariantDef (const VariantDef &other)
+ : id (other.id), defid (other.defid), identifier (other.identifier),
+ ident (other.ident), type (other.type), discriminant (other.discriminant),
+ fields (other.fields)
+{}
- // we must need to fill out defaults
- size_t left_over
- = num_required_substitutions () - min_required_substitutions ();
- if (left_over > 0)
- {
- for (size_t offs = mappings.size (); offs < substitutions.size (); offs++)
- {
- SubstitutionParamMapping &param = substitutions.at (offs);
- rust_assert (param.param_has_default_ty ());
+VariantDef &
+VariantDef::operator= (const VariantDef &other)
+{
+ id = other.id;
+ identifier = other.identifier;
+ type = other.type;
+ discriminant = other.discriminant;
+ fields = other.fields;
+ ident = other.ident;
- BaseType *resolved = param.get_default_ty ();
- if (resolved->get_kind () == TypeKind::ERROR)
- return SubstitutionArgumentMappings::error ();
+ return *this;
+}
- // this resolved default might already contain default parameters
- if (resolved->contains_type_parameters ())
- {
- SubstitutionArgumentMappings intermediate (mappings,
- binding_arguments,
- args.get_locus ());
- resolved = Resolver::SubstMapperInternal::Resolve (resolved,
- intermediate);
-
- if (resolved->get_kind () == TypeKind::ERROR)
- return SubstitutionArgumentMappings::error ();
- }
+VariantDef &
+VariantDef::get_error_node ()
+{
+ static VariantDef node
+ = VariantDef (UNKNOWN_HIRID, UNKNOWN_DEFID, "",
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::unknown_location ()},
+ nullptr);
- SubstitutionArg subst_arg (&param, resolved);
- mappings.push_back (std::move (subst_arg));
- }
- }
+ return node;
+}
- return SubstitutionArgumentMappings (mappings, binding_arguments,
- args.get_locus ());
+bool
+VariantDef::is_error () const
+{
+ return get_id () == UNKNOWN_HIRID;
}
-BaseType *
-SubstitutionRef::infer_substitions (Location locus)
+HirId
+VariantDef::get_id () const
{
- std::vector<SubstitutionArg> args;
- std::map<std::string, BaseType *> argument_mappings;
- for (auto &p : get_substs ())
- {
- if (p.needs_substitution ())
- {
- const std::string &symbol = p.get_param_ty ()->get_symbol ();
- auto it = argument_mappings.find (symbol);
- bool have_mapping = it != argument_mappings.end ();
+ return id;
+}
- if (have_mapping)
- {
- args.push_back (SubstitutionArg (&p, it->second));
- }
- else
- {
- TyVar infer_var = TyVar::get_implicit_infer_var (locus);
- args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
- argument_mappings[symbol] = infer_var.get_tyty ();
- }
- }
- else
- {
- args.push_back (SubstitutionArg (&p, p.get_param_ty ()->resolve ()));
- }
- }
+DefId
+VariantDef::get_defid () const
+{
+ return defid;
+}
- // FIXME do we need to add inference variables to all the possible bindings?
- // it might just lead to inference variable hell not 100% sure if rustc does
- // this i think the language might needs this to be explicitly set
+VariantDef::VariantType
+VariantDef::get_variant_type () const
+{
+ return type;
+}
- SubstitutionArgumentMappings infer_arguments (std::move (args),
- {} /* binding_arguments */,
- locus);
- return handle_substitions (std::move (infer_arguments));
+bool
+VariantDef::is_data_variant () const
+{
+ return type != VariantType::NUM;
}
-SubstitutionArgumentMappings
-SubstitutionRef::adjust_mappings_for_this (
- SubstitutionArgumentMappings &mappings)
+bool
+VariantDef::is_dataless_variant () const
{
- std::vector<SubstitutionArg> resolved_mappings;
- for (size_t i = 0; i < substitutions.size (); i++)
- {
- auto &subst = substitutions.at (i);
+ return type == VariantType::NUM;
+}
- SubstitutionArg arg = SubstitutionArg::error ();
- if (mappings.size () == substitutions.size ())
- {
- mappings.get_argument_at (i, &arg);
- }
- else
- {
- if (subst.needs_substitution ())
- {
- // get from passed in mappings
- mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
- }
- else
- {
- // we should already have this somewhere
- used_arguments.get_argument_for_symbol (subst.get_param_ty (),
- &arg);
- }
- }
+std::string
+VariantDef::get_identifier () const
+{
+ return identifier;
+}
- bool ok = !arg.is_error ();
- if (ok)
- {
- SubstitutionArg adjusted (&subst, arg.get_tyty ());
- resolved_mappings.push_back (std::move (adjusted));
- }
- }
+size_t
+VariantDef::num_fields () const
+{
+ return fields.size ();
+}
- if (resolved_mappings.empty ())
- return SubstitutionArgumentMappings::error ();
+StructFieldType *
+VariantDef::get_field_at_index (size_t index)
+{
+ rust_assert (index < fields.size ());
+ return fields.at (index);
+}
- return SubstitutionArgumentMappings (resolved_mappings,
- mappings.get_binding_args (),
- mappings.get_locus (),
- mappings.get_subst_cb (),
- mappings.trait_item_mode ());
+std::vector<StructFieldType *> &
+VariantDef::get_fields ()
+{
+ rust_assert (type != NUM);
+ return fields;
}
bool
-SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings)
+VariantDef::lookup_field (const std::string &lookup,
+ StructFieldType **field_lookup, size_t *index) const
{
- std::vector<SubstitutionArg> resolved_mappings;
- for (size_t i = 0; i < substitutions.size (); i++)
+ size_t i = 0;
+ for (auto &field : fields)
{
- auto &subst = substitutions.at (i);
-
- SubstitutionArg arg = SubstitutionArg::error ();
- if (mappings.size () == substitutions.size ())
- {
- mappings.get_argument_at (i, &arg);
- }
- else
+ if (field->get_name ().compare (lookup) == 0)
{
- if (subst.needs_substitution ())
- {
- // get from passed in mappings
- mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
- }
- else
- {
- // we should already have this somewhere
- used_arguments.get_argument_for_symbol (subst.get_param_ty (),
- &arg);
- }
- }
+ if (index != nullptr)
+ *index = i;
- bool ok = !arg.is_error ();
- if (ok)
- {
- SubstitutionArg adjusted (&subst, arg.get_tyty ());
- resolved_mappings.push_back (std::move (adjusted));
+ if (field_lookup != nullptr)
+ *field_lookup = field;
+
+ return true;
}
+ i++;
}
+ return false;
+}
- return !resolved_mappings.empty ();
+HIR::Expr *
+VariantDef::get_discriminant () const
+{
+ rust_assert (discriminant != nullptr);
+ return discriminant;
}
-// this function assumes that the mappings being passed are for the same type as
-// this new substitution reference so ordering matters here
-SubstitutionArgumentMappings
-SubstitutionRef::solve_mappings_from_receiver_for_self (
- SubstitutionArgumentMappings &mappings) const
+std::string
+VariantDef::as_string () const
{
- std::vector<SubstitutionArg> resolved_mappings;
+ if (type == VariantType::NUM)
+ return identifier + " = " + discriminant->as_string ();
- rust_assert (mappings.size () == get_num_substitutions ());
- for (size_t i = 0; i < get_num_substitutions (); i++)
+ std::string buffer;
+ for (size_t i = 0; i < fields.size (); ++i)
{
- const SubstitutionParamMapping &param_mapping = substitutions.at (i);
- SubstitutionArg &arg = mappings.get_mappings ().at (i);
-
- if (param_mapping.needs_substitution ())
- {
- SubstitutionArg adjusted (&param_mapping, arg.get_tyty ());
- resolved_mappings.push_back (std::move (adjusted));
- }
+ buffer += fields.at (i)->as_string ();
+ if ((i + 1) < fields.size ())
+ buffer += ", ";
}
- return SubstitutionArgumentMappings (resolved_mappings,
- mappings.get_binding_args (),
- mappings.get_locus ());
+ if (type == VariantType::TUPLE)
+ return identifier + " (" + buffer + ")";
+ else
+ return identifier + " {" + buffer + "}";
}
-SubstitutionArgumentMappings
-SubstitutionRef::solve_missing_mappings_from_this (SubstitutionRef &ref,
- SubstitutionRef &to)
+bool
+VariantDef::is_equal (const VariantDef &other) const
{
- rust_assert (!ref.needs_substitution ());
- rust_assert (needs_substitution ());
- rust_assert (get_num_substitutions () == ref.get_num_substitutions ());
-
- Location locus = used_arguments.get_locus ();
- std::vector<SubstitutionArg> resolved_mappings;
+ if (type != other.type)
+ return false;
- std::map<HirId, std::pair<ParamType *, BaseType *>> substs;
- for (size_t i = 0; i < get_num_substitutions (); i++)
- {
- SubstitutionParamMapping &a = substitutions.at (i);
- SubstitutionParamMapping &b = ref.substitutions.at (i);
+ if (identifier.compare (other.identifier) != 0)
+ return false;
- if (a.need_substitution ())
- {
- const BaseType *root = a.get_param_ty ()->resolve ()->get_root ();
- rust_assert (root->get_kind () == TyTy::TypeKind::PARAM);
- const ParamType *p = static_cast<const TyTy::ParamType *> (root);
+ if (discriminant != other.discriminant)
+ return false;
- substs[p->get_ty_ref ()] = {static_cast<ParamType *> (p->clone ()),
- b.get_param_ty ()->resolve ()};
- }
- }
+ if (fields.size () != other.fields.size ())
+ return false;
- for (auto it = substs.begin (); it != substs.end (); it++)
+ for (size_t i = 0; i < fields.size (); i++)
{
- HirId param_id = it->first;
- BaseType *arg = it->second.second;
-
- const SubstitutionParamMapping *associate_param = nullptr;
- for (SubstitutionParamMapping &p : to.substitutions)
- {
- if (p.get_param_ty ()->get_ty_ref () == param_id)
- {
- associate_param = &p;
- break;
- }
- }
-
- rust_assert (associate_param != nullptr);
- SubstitutionArg argument (associate_param, arg);
- resolved_mappings.push_back (std::move (argument));
+ if (!fields.at (i)->is_equal (*other.fields.at (i)))
+ return false;
}
- return SubstitutionArgumentMappings (resolved_mappings, {}, locus);
+ return true;
}
-bool
-SubstitutionRef::monomorphize ()
+VariantDef *
+VariantDef::clone () const
{
- auto context = Resolver::TypeCheckContext::get ();
- for (const auto &subst : get_substs ())
- {
- const TyTy::ParamType *pty = subst.get_param_ty ();
-
- if (!pty->can_resolve ())
- continue;
+ std::vector<StructFieldType *> cloned_fields;
+ for (auto &f : fields)
+ cloned_fields.push_back ((StructFieldType *) f->clone ());
- const TyTy::BaseType *binding = pty->resolve ();
- if (binding->get_kind () == TyTy::TypeKind::PARAM)
- continue;
-
- for (const auto &bound : pty->get_specified_bounds ())
- {
- const Resolver::TraitReference *specified_bound_ref = bound.get ();
-
- // setup any associated type mappings for the specified bonds and this
- // type
- auto candidates = Resolver::TypeBoundsProbe::Probe (binding);
+ return new VariantDef (id, defid, identifier, ident, type, discriminant,
+ cloned_fields);
+}
- Resolver::AssociatedImplTrait *associated_impl_trait = nullptr;
- for (auto &probed_bound : candidates)
- {
- const Resolver::TraitReference *bound_trait_ref
- = probed_bound.first;
- const HIR::ImplBlock *associated_impl = probed_bound.second;
-
- HirId impl_block_id
- = associated_impl->get_mappings ().get_hirid ();
- Resolver::AssociatedImplTrait *associated = nullptr;
- bool found_impl_trait
- = context->lookup_associated_trait_impl (impl_block_id,
- &associated);
- if (found_impl_trait)
- {
- bool found_trait
- = specified_bound_ref->is_equal (*bound_trait_ref);
- bool found_self
- = associated->get_self ()->can_eq (binding, false);
- if (found_trait && found_self)
- {
- associated_impl_trait = associated;
- break;
- }
- }
- }
+VariantDef *
+VariantDef::monomorphized_clone () const
+{
+ std::vector<StructFieldType *> cloned_fields;
+ for (auto &f : fields)
+ cloned_fields.push_back ((StructFieldType *) f->monomorphized_clone ());
- if (associated_impl_trait != nullptr)
- {
- associated_impl_trait->setup_associated_types (binding, bound);
- }
- }
- }
+ return new VariantDef (id, defid, identifier, ident, type, discriminant,
+ cloned_fields);
+}
- return true;
+const RustIdent &
+VariantDef::get_ident () const
+{
+ return ident;
}
+// ADTType
+
void
ADTType::accept_vis (TyVisitor &vis)
{
@@ -1097,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
{
@@ -1236,7 +1185,7 @@ handle_substitions (SubstitutionArgumentMappings &subst_mappings,
}
ADTType *
-ADTType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
+ADTType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
{
ADTType *adt = static_cast<ADTType *> (clone ());
adt->set_ty_ref (mappings->get_next_hir_id ());
@@ -1267,6 +1216,57 @@ ADTType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
return adt;
}
+// TupleType
+
+TupleType::TupleType (HirId ref, Location locus, std::vector<TyVar> fields,
+ std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::TUPLE,
+ {Resolver::CanonicalPath::create_empty (), locus}, refs),
+ fields (fields)
+{}
+
+TupleType::TupleType (HirId ref, HirId ty_ref, Location locus,
+ std::vector<TyVar> fields, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::TUPLE,
+ {Resolver::CanonicalPath::create_empty (), locus}, refs),
+ fields (fields)
+{}
+
+TupleType *
+TupleType::get_unit_type (HirId ref)
+{
+ return new TupleType (ref, Linemap::predeclared_location ());
+}
+
+bool
+TupleType::is_unit () const
+{
+ return this->fields.empty ();
+}
+
+size_t
+TupleType::num_fields () const
+{
+ return fields.size ();
+}
+
+bool
+TupleType::is_concrete () const
+{
+ for (size_t i = 0; i < num_fields (); i++)
+ {
+ if (!get_field (i)->is_concrete ())
+ return false;
+ }
+ return true;
+}
+
+const std::vector<TyVar> &
+TupleType::get_fields () const
+{
+ return fields;
+}
+
void
TupleType::accept_vis (TyVisitor &vis)
{
@@ -1315,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
{
@@ -1370,7 +1363,7 @@ TupleType::monomorphized_clone () const
}
TupleType *
-TupleType::handle_substitions (SubstitutionArgumentMappings mappings)
+TupleType::handle_substitions (SubstitutionArgumentMappings &mappings)
{
auto mappings_table = Analysis::Mappings::get ();
@@ -1422,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
{
@@ -1511,7 +1497,7 @@ FnType::monomorphized_clone () const
}
FnType *
-FnType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
+FnType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
{
FnType *fn = static_cast<FnType *> (clone ());
fn->set_ty_ref (mappings->get_next_hir_id ());
@@ -1653,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
{
@@ -1733,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
{
@@ -1779,7 +1751,7 @@ ClosureType::monomorphized_clone () const
}
ClosureType *
-ClosureType::handle_substitions (SubstitutionArgumentMappings mappings)
+ClosureType::handle_substitions (SubstitutionArgumentMappings &mappings)
{
gcc_unreachable ();
return nullptr;
@@ -1849,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
{
@@ -1899,7 +1864,7 @@ ArrayType::monomorphized_clone () const
}
ArrayType *
-ArrayType::handle_substitions (SubstitutionArgumentMappings mappings)
+ArrayType::handle_substitions (SubstitutionArgumentMappings &mappings)
{
auto mappings_table = Analysis::Mappings::get ();
@@ -1932,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
{
@@ -1982,7 +1940,7 @@ SliceType::monomorphized_clone () const
}
SliceType *
-SliceType::handle_substitions (SubstitutionArgumentMappings mappings)
+SliceType::handle_substitions (SubstitutionArgumentMappings &mappings)
{
auto mappings_table = Analysis::Mappings::get ();
@@ -1997,6 +1955,34 @@ SliceType::handle_substitions (SubstitutionArgumentMappings mappings)
return ref;
}
+// BoolType
+
+BoolType::BoolType (HirId ref, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::BOOL,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+BoolType::BoolType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::BOOL,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+std::string
+BoolType::get_name () const
+{
+ return as_string ();
+}
+
+bool
+BoolType::is_concrete () const
+{
+ return true;
+}
+
void
BoolType::accept_vis (TyVisitor &vis)
{
@@ -2015,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
{
@@ -2041,6 +2020,36 @@ BoolType::monomorphized_clone () const
return clone ();
}
+// IntType
+
+IntType::IntType (HirId ref, IntKind kind, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::INT,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ int_kind (kind)
+{}
+
+IntType::IntType (HirId ref, HirId ty_ref, IntKind kind, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::INT,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ int_kind (kind)
+{}
+
+std::string
+IntType::get_name () const
+{
+ return as_string ();
+}
+
+IntType::IntKind
+IntType::get_int_kind () const
+{
+ return int_kind;
+}
+
void
IntType::accept_vis (TyVisitor &vis)
{
@@ -2073,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
{
@@ -2110,6 +2112,43 @@ IntType::is_equal (const BaseType &other) const
return get_int_kind () == o.get_int_kind ();
}
+bool
+IntType::is_concrete () const
+{
+ return true;
+}
+
+// UintType
+
+UintType::UintType (HirId ref, UintKind kind, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::UINT,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ uint_kind (kind)
+{}
+
+UintType::UintType (HirId ref, HirId ty_ref, UintKind kind,
+ std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::UINT,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ uint_kind (kind)
+{}
+
+std::string
+UintType::get_name () const
+{
+ return as_string ();
+}
+
+UintType::UintKind
+UintType::get_uint_kind () const
+{
+ return uint_kind;
+}
+
void
UintType::accept_vis (TyVisitor &vis)
{
@@ -2142,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
{
@@ -2179,6 +2211,49 @@ UintType::is_equal (const BaseType &other) const
return get_uint_kind () == o.get_uint_kind ();
}
+bool
+UintType::is_concrete () const
+{
+ return true;
+}
+
+// FloatType
+
+FloatType::FloatType (HirId ref, FloatKind kind, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::FLOAT,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ float_kind (kind)
+{}
+
+FloatType::FloatType (HirId ref, HirId ty_ref, FloatKind kind,
+ std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::FLOAT,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ float_kind (kind)
+{}
+
+std::string
+FloatType::get_name () const
+{
+ return as_string ();
+}
+
+FloatType::FloatKind
+FloatType::get_float_kind () const
+{
+ return float_kind;
+}
+
+bool
+FloatType::is_concrete () const
+{
+ return true;
+}
+
void
FloatType::accept_vis (TyVisitor &vis)
{
@@ -2205,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
{
@@ -2242,6 +2310,34 @@ FloatType::is_equal (const BaseType &other) const
return get_float_kind () == o.get_float_kind ();
}
+// UsizeType
+
+USizeType::USizeType (HirId ref, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::USIZE,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+USizeType::USizeType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::USIZE,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+std::string
+USizeType::get_name () const
+{
+ return as_string ();
+}
+
+bool
+USizeType::is_concrete () const
+{
+ return true;
+}
+
void
USizeType::accept_vis (TyVisitor &vis)
{
@@ -2260,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
{
@@ -2286,6 +2375,34 @@ USizeType::monomorphized_clone () const
return clone ();
}
+// ISizeType
+
+ISizeType::ISizeType (HirId ref, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::ISIZE,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+ISizeType::ISizeType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::ISIZE,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+std::string
+ISizeType::get_name () const
+{
+ return as_string ();
+}
+
+bool
+ISizeType::is_concrete () const
+{
+ return true;
+}
+
void
ISizeType::accept_vis (TyVisitor &vis)
{
@@ -2304,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
{
@@ -2330,6 +2440,34 @@ ISizeType::monomorphized_clone () const
return clone ();
}
+// Char Type
+
+CharType::CharType (HirId ref, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::CHAR,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+CharType::CharType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::CHAR,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+bool
+CharType::is_concrete () const
+{
+ return true;
+}
+
+std::string
+CharType::get_name () const
+{
+ return as_string ();
+}
+
void
CharType::accept_vis (TyVisitor &vis)
{
@@ -2348,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
{
@@ -2374,6 +2505,76 @@ CharType::monomorphized_clone () const
return clone ();
}
+// Reference Type
+
+ReferenceType::ReferenceType (HirId ref, TyVar base, Mutability mut,
+ std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::REF,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ base (base), mut (mut)
+{}
+
+ReferenceType::ReferenceType (HirId ref, HirId ty_ref, TyVar base,
+ Mutability mut, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::REF,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ base (base), mut (mut)
+{}
+
+bool
+ReferenceType::is_concrete () const
+{
+ return get_base ()->is_concrete ();
+}
+
+Mutability
+ReferenceType::mutability () const
+{
+ return mut;
+}
+
+bool
+ReferenceType::is_mutable () const
+{
+ return mut == Mutability::Mut;
+}
+
+bool
+ReferenceType::is_dyn_object () const
+{
+ return is_dyn_slice_type () || is_dyn_str_type ();
+}
+
+bool
+ReferenceType::is_dyn_slice_type (const TyTy::SliceType **slice) const
+{
+ const TyTy::BaseType *element = get_base ()->destructure ();
+ if (element->get_kind () != TyTy::TypeKind::SLICE)
+ return false;
+ if (slice == nullptr)
+ return true;
+
+ *slice = static_cast<const TyTy::SliceType *> (element);
+ return true;
+}
+
+bool
+ReferenceType::is_dyn_str_type (const TyTy::StrType **str) const
+{
+ const TyTy::BaseType *element = get_base ()->destructure ();
+ if (element->get_kind () != TyTy::TypeKind::STR)
+ return false;
+ if (str == nullptr)
+ return true;
+
+ *str = static_cast<const TyTy::StrType *> (element);
+ return true;
+}
+
void
ReferenceType::accept_vis (TyVisitor &vis)
{
@@ -2400,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
{
@@ -2449,7 +2643,7 @@ ReferenceType::monomorphized_clone () const
}
ReferenceType *
-ReferenceType::handle_substitions (SubstitutionArgumentMappings mappings)
+ReferenceType::handle_substitions (SubstitutionArgumentMappings &mappings)
{
auto mappings_table = Analysis::Mappings::get ();
@@ -2464,6 +2658,82 @@ ReferenceType::handle_substitions (SubstitutionArgumentMappings mappings)
return ref;
}
+// PointerType
+
+PointerType::PointerType (HirId ref, TyVar base, Mutability mut,
+ std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::POINTER,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ base (base), mut (mut)
+{}
+
+PointerType::PointerType (HirId ref, HirId ty_ref, TyVar base, Mutability mut,
+ std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::POINTER,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ base (base), mut (mut)
+{}
+
+bool
+PointerType::is_concrete () const
+{
+ return get_base ()->is_concrete ();
+}
+
+Mutability
+PointerType::mutability () const
+{
+ return mut;
+}
+
+bool
+PointerType::is_mutable () const
+{
+ return mut == Mutability::Mut;
+}
+
+bool
+PointerType::is_const () const
+{
+ return mut == Mutability::Imm;
+}
+
+bool
+PointerType::is_dyn_object () const
+{
+ return is_dyn_slice_type () || is_dyn_str_type ();
+}
+
+bool
+PointerType::is_dyn_slice_type (const TyTy::SliceType **slice) const
+{
+ const TyTy::BaseType *element = get_base ()->destructure ();
+ if (element->get_kind () != TyTy::TypeKind::SLICE)
+ return false;
+ if (slice == nullptr)
+ return true;
+
+ *slice = static_cast<const TyTy::SliceType *> (element);
+ return true;
+}
+
+bool
+PointerType::is_dyn_str_type (const TyTy::StrType **str) const
+{
+ const TyTy::BaseType *element = get_base ()->destructure ();
+ if (element->get_kind () != TyTy::TypeKind::STR)
+ return false;
+ if (str == nullptr)
+ return true;
+
+ *str = static_cast<const TyTy::StrType *> (element);
+ return true;
+}
+
void
PointerType::accept_vis (TyVisitor &vis)
{
@@ -2490,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
{
@@ -2539,7 +2802,7 @@ PointerType::monomorphized_clone () const
}
PointerType *
-PointerType::handle_substitions (SubstitutionArgumentMappings mappings)
+PointerType::handle_substitions (SubstitutionArgumentMappings &mappings)
{
auto mappings_table = Analysis::Mappings::get ();
@@ -2554,6 +2817,52 @@ PointerType::handle_substitions (SubstitutionArgumentMappings mappings)
return ref;
}
+// PARAM Type
+
+ParamType::ParamType (std::string symbol, Location locus, HirId ref,
+ HIR::GenericParam &param,
+ std::vector<TypeBoundPredicate> specified_bounds,
+ std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::PARAM,
+ {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
+ locus},
+ specified_bounds, refs),
+ symbol (symbol), param (param)
+{}
+
+ParamType::ParamType (std::string symbol, Location locus, HirId ref,
+ HirId ty_ref, HIR::GenericParam &param,
+ std::vector<TypeBoundPredicate> specified_bounds,
+ std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::PARAM,
+ {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
+ locus},
+ specified_bounds, refs),
+ symbol (symbol), param (param)
+{}
+
+HIR::GenericParam &
+ParamType::get_generic_param ()
+{
+ return param;
+}
+
+bool
+ParamType::can_resolve () const
+{
+ return get_ref () != get_ty_ref ();
+}
+
+bool
+ParamType::is_concrete () const
+{
+ auto r = resolve ();
+ if (r == this)
+ return false;
+
+ return r->is_concrete ();
+}
+
void
ParamType::accept_vis (TyVisitor &vis)
{
@@ -2587,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
{
@@ -2670,7 +2972,7 @@ ParamType::is_equal (const BaseType &other) const
}
ParamType *
-ParamType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
+ParamType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
{
SubstitutionArg arg = SubstitutionArg::error ();
bool ok = subst_mappings.get_argument_for_symbol (this, &arg);
@@ -2695,6 +2997,34 @@ ParamType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
return p;
}
+// StrType
+
+StrType::StrType (HirId ref, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::STR,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+StrType::StrType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::STR,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+std::string
+StrType::get_name () const
+{
+ return as_string ();
+}
+
+bool
+StrType::is_concrete () const
+{
+ return true;
+}
+
BaseType *
StrType::clone () const
{
@@ -2725,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
{
@@ -2745,6 +3068,40 @@ StrType::is_equal (const BaseType &other) const
return get_kind () == other.get_kind ();
}
+// Never Type
+
+NeverType::NeverType (HirId ref, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::NEVER,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+NeverType::NeverType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::NEVER,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+std::string
+NeverType::get_name () const
+{
+ return as_string ();
+}
+
+bool
+NeverType::is_unit () const
+{
+ return true;
+}
+
+bool
+NeverType::is_concrete () const
+{
+ return true;
+}
+
void
NeverType::accept_vis (TyVisitor &vis)
{
@@ -2763,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
{
@@ -2791,6 +3141,52 @@ NeverType::monomorphized_clone () const
// placeholder type
+PlaceholderType::PlaceholderType (std::string symbol, HirId ref,
+ std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::PLACEHOLDER,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ symbol (symbol)
+{}
+
+PlaceholderType::PlaceholderType (std::string symbol, HirId ref, HirId ty_ref,
+ std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::PLACEHOLDER,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ symbol (symbol)
+{}
+
+std::string
+PlaceholderType::get_name () const
+{
+ return as_string ();
+}
+
+bool
+PlaceholderType::is_unit () const
+{
+ rust_assert (can_resolve ());
+ return resolve ()->is_unit ();
+}
+
+std::string
+PlaceholderType::get_symbol () const
+{
+ return symbol;
+}
+
+bool
+PlaceholderType::is_concrete () const
+{
+ if (!can_resolve ())
+ return true;
+
+ return resolve ()->is_concrete ();
+}
+
void
PlaceholderType::accept_vis (TyVisitor &vis)
{
@@ -2810,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
{
@@ -2890,6 +3279,78 @@ PlaceholderType::is_equal (const BaseType &other) const
// Projection type
+ProjectionType::ProjectionType (
+ HirId ref, BaseType *base, const Resolver::TraitReference *trait, DefId item,
+ std::vector<SubstitutionParamMapping> subst_refs,
+ SubstitutionArgumentMappings generic_arguments, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::PROJECTION,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
+ base (base), trait (trait), item (item)
+{}
+
+ProjectionType::ProjectionType (
+ HirId ref, HirId ty_ref, BaseType *base,
+ const Resolver::TraitReference *trait, DefId item,
+ std::vector<SubstitutionParamMapping> subst_refs,
+ SubstitutionArgumentMappings generic_arguments, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::PROJECTION,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
+ base (base), trait (trait), item (item)
+{}
+
+bool
+ProjectionType::is_unit () const
+{
+ return false;
+}
+
+std::string
+ProjectionType::get_name () const
+{
+ return as_string ();
+}
+
+bool
+ProjectionType::needs_generic_substitutions () const
+{
+ return needs_substitution ();
+}
+
+bool
+ProjectionType::supports_substitutions () const
+{
+ return true;
+}
+
+bool
+ProjectionType::has_subsititions_defined () const
+{
+ return has_substitutions ();
+}
+
+const BaseType *
+ProjectionType::get () const
+{
+ return base;
+}
+BaseType *
+ProjectionType::get ()
+{
+ return base;
+}
+
+bool
+ProjectionType::is_concrete () const
+{
+ return base->is_concrete ();
+}
+
void
ProjectionType::accept_vis (TyVisitor &vis)
{
@@ -2908,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
{
@@ -2935,7 +3390,8 @@ ProjectionType::monomorphized_clone () const
}
ProjectionType *
-ProjectionType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
+ProjectionType::handle_substitions (
+ SubstitutionArgumentMappings &subst_mappings)
{
// // do we really need to substitute this?
// if (base->needs_generic_substitutions () || base->contains_type_parameters
@@ -3006,6 +3462,26 @@ ProjectionType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
return projection;
}
+// DynObjectType
+
+DynamicObjectType::DynamicObjectType (
+ HirId ref, RustIdent ident, std::vector<TypeBoundPredicate> specified_bounds,
+ std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
+{}
+
+DynamicObjectType::DynamicObjectType (
+ HirId ref, HirId ty_ref, RustIdent ident,
+ std::vector<TypeBoundPredicate> specified_bounds, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
+{}
+
+bool
+DynamicObjectType::is_concrete () const
+{
+ return true;
+}
+
void
DynamicObjectType::accept_vis (TyVisitor &vis)
{
@@ -3024,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
{
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 4f333a8..89c3209 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -20,11 +20,12 @@
#define RUST_TYTY
#include "rust-hir-map.h"
-#include "rust-hir-full.h"
-#include "rust-diagnostics.h"
-#include "rust-abi.h"
#include "rust-common.h"
#include "rust-identifier.h"
+#include "rust-abi.h"
+#include "rust-tyty-bounds.h"
+#include "rust-tyty-util.h"
+#include "rust-tyty-subst.h"
namespace Rust {
@@ -76,65 +77,6 @@ public:
static std::string to_string (TypeKind kind);
};
-class BaseType;
-class TypeBoundPredicate;
-class TypeBoundPredicateItem
-{
-public:
- TypeBoundPredicateItem (const TypeBoundPredicate *parent,
- const Resolver::TraitItemReference *trait_item_ref)
- : parent (parent), trait_item_ref (trait_item_ref)
- {}
-
- static TypeBoundPredicateItem error ()
- {
- return TypeBoundPredicateItem (nullptr, nullptr);
- }
-
- bool is_error () const
- {
- return parent == nullptr || trait_item_ref == nullptr;
- }
-
- BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver);
-
- const Resolver::TraitItemReference *get_raw_item () const;
-
- bool needs_implementation () const;
-
- const TypeBoundPredicate *get_parent () const { return parent; }
-
- Location get_locus () const;
-
-private:
- const TypeBoundPredicate *parent;
- const Resolver::TraitItemReference *trait_item_ref;
-};
-
-class TypeBoundsMappings
-{
-protected:
- TypeBoundsMappings (std::vector<TypeBoundPredicate> specified_bounds);
-
-public:
- std::vector<TypeBoundPredicate> &get_specified_bounds ();
-
- const std::vector<TypeBoundPredicate> &get_specified_bounds () const;
-
- size_t num_specified_bounds () const;
-
- std::string raw_bounds_as_string () const;
-
- std::string bounds_as_string () const;
-
- std::string raw_bounds_as_name () const;
-
-protected:
- void add_bound (TypeBoundPredicate predicate);
-
- std::vector<TypeBoundPredicate> specified_bounds;
-};
-
extern void
set_cmp_autoderef_mode ();
extern void
@@ -145,20 +87,15 @@ class TyConstVisitor;
class BaseType : public TypeBoundsMappings
{
public:
- virtual ~BaseType () {}
+ virtual ~BaseType ();
- HirId get_ref () const { return ref; }
+ HirId get_ref () const;
- void set_ref (HirId id)
- {
- if (id != ref)
- append_reference (ref);
- ref = id;
- }
+ void set_ref (HirId id);
- HirId get_ty_ref () const { return ty_ref; }
+ HirId get_ty_ref () const;
- void set_ty_ref (HirId id) { ty_ref = id; }
+ void set_ty_ref (HirId id);
virtual void accept_vis (TyVisitor &vis) = 0;
@@ -168,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
//
@@ -189,10 +121,7 @@ public:
// ty are considered equal if they're of the same kind, and
// 1. (For ADTs, arrays, tuples, refs) have the same underlying ty
// 2. (For functions) have the same signature
- virtual bool is_equal (const BaseType &other) const
- {
- return get_kind () == other.get_kind ();
- }
+ virtual bool is_equal (const BaseType &other) const;
bool satisfies_bound (const TypeBoundPredicate &predicate) const;
@@ -204,11 +133,11 @@ public:
void inherit_bounds (
const std::vector<TyTy::TypeBoundPredicate> &specified_bounds);
- virtual bool is_unit () const { return false; }
+ virtual bool is_unit () const;
virtual bool is_concrete () const = 0;
- TypeKind get_kind () const { return kind; }
+ TypeKind get_kind () const;
/* Returns a pointer to a clone of this. The caller is responsible for
* releasing the memory of the returned ty. */
@@ -218,22 +147,19 @@ public:
virtual BaseType *monomorphized_clone () const = 0;
// get_combined_refs returns the chain of node refs involved in unification
- std::set<HirId> get_combined_refs () const { return combined; }
+ std::set<HirId> get_combined_refs () const;
- void append_reference (HirId id) { combined.insert (id); }
+ void append_reference (HirId id);
- virtual bool supports_substitutions () const { return false; }
+ virtual bool supports_substitutions () const;
- virtual bool has_subsititions_defined () const { return false; }
+ virtual bool has_subsititions_defined () const;
- virtual bool can_substitute () const
- {
- return supports_substitutions () && has_subsititions_defined ();
- }
+ virtual bool can_substitute () const;
- virtual bool needs_generic_substitutions () const { return false; }
+ virtual bool needs_generic_substitutions () const;
- bool contains_type_parameters () const { return !is_concrete (); }
+ bool contains_type_parameters () const;
std::string mappings_str () const;
@@ -246,26 +172,20 @@ 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 { return ident; }
+ const RustIdent &get_ident () const;
- Location get_locus () const { return ident.locus; }
+ Location get_locus () const;
protected:
BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
- std::set<HirId> refs = std::set<HirId> ())
- : TypeBoundsMappings ({}), kind (kind), ref (ref), ty_ref (ty_ref),
- combined (refs), ident (ident), mappings (Analysis::Mappings::get ())
- {}
+ std::set<HirId> refs = std::set<HirId> ());
BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
std::vector<TypeBoundPredicate> specified_bounds,
- std::set<HirId> refs = std::set<HirId> ())
- : TypeBoundsMappings (specified_bounds), kind (kind), ref (ref),
- ty_ref (ty_ref), combined (refs), ident (ident),
- mappings (Analysis::Mappings::get ())
- {}
+ std::set<HirId> refs = std::set<HirId> ());
TypeKind kind;
HirId ref;
@@ -276,43 +196,6 @@ protected:
Analysis::Mappings *mappings;
};
-// this is a placeholder for types that can change like inference variables
-class TyVar
-{
-public:
- explicit TyVar (HirId ref);
-
- HirId get_ref () const { return ref; }
-
- BaseType *get_tyty () const;
-
- TyVar clone () const;
-
- TyVar monomorphized_clone () const;
-
- static TyVar get_implicit_infer_var (Location locus);
-
- static TyVar subst_covariant_var (TyTy::BaseType *orig,
- TyTy::BaseType *subst);
-
-private:
- HirId ref;
-};
-
-class TyWithLocation
-{
-public:
- explicit TyWithLocation (BaseType *ty, Location locus);
- explicit TyWithLocation (BaseType *ty);
-
- BaseType *get_ty () const { return ty; }
- Location get_locus () const { return locus; }
-
-private:
- BaseType *ty;
- Location locus;
-};
-
class InferType : public BaseType
{
public:
@@ -324,38 +207,28 @@ public:
};
InferType (HirId ref, InferTypeKind infer_kind, Location locus,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::INFER,
- {Resolver::CanonicalPath::create_empty (), locus}, refs),
- infer_kind (infer_kind)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
InferType (HirId ref, HirId ty_ref, InferTypeKind infer_kind, Location locus,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::INFER,
- {Resolver::CanonicalPath::create_empty (), locus}, refs),
- infer_kind (infer_kind)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
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;
BaseType *monomorphized_clone () const final override;
- InferTypeKind get_infer_kind () const { return infer_kind; }
+ InferTypeKind get_infer_kind () const;
- std::string get_name () const override final { return as_string (); }
+ std::string get_name () const override final;
bool default_type (BaseType **type) const;
- bool is_concrete () const final override { return true; }
+ bool is_concrete () const final override;
private:
InferTypeKind infer_kind;
@@ -364,66 +237,46 @@ private:
class ErrorType : public BaseType
{
public:
- ErrorType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::ERROR,
- {Resolver::CanonicalPath::create_empty (), Location ()}, refs)
- {}
+ ErrorType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
- ErrorType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::ERROR,
- {Resolver::CanonicalPath::create_empty (), Location ()}, refs)
- {}
+ ErrorType (HirId ref, HirId ty_ref,
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
- bool is_unit () const override { return true; }
+ bool is_unit () const override;
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;
BaseType *monomorphized_clone () const final override;
- std::string get_name () const override final { return as_string (); }
+ std::string get_name () const override final;
- bool is_concrete () const final override { return false; }
+ bool is_concrete () const final override;
};
-class SubstitutionArgumentMappings;
class ParamType : public BaseType
{
public:
ParamType (std::string symbol, Location locus, HirId ref,
HIR::GenericParam &param,
std::vector<TypeBoundPredicate> specified_bounds,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::PARAM,
- {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
- locus},
- specified_bounds, refs),
- symbol (symbol), param (param)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
ParamType (std::string symbol, Location locus, HirId ref, HirId ty_ref,
HIR::GenericParam &param,
std::vector<TypeBoundPredicate> specified_bounds,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::PARAM,
- {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
- locus},
- specified_bounds, refs),
- symbol (symbol), param (param)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
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;
@@ -431,9 +284,9 @@ public:
std::string get_symbol () const;
- HIR::GenericParam &get_generic_param () { return param; }
+ HIR::GenericParam &get_generic_param ();
- bool can_resolve () const { return get_ref () != get_ty_ref (); }
+ bool can_resolve () const;
BaseType *resolve () const;
@@ -441,16 +294,9 @@ public:
bool is_equal (const BaseType &other) const override;
- bool is_concrete () const override final
- {
- auto r = resolve ();
- if (r == this)
- return false;
-
- return r->is_concrete ();
- }
+ bool is_concrete () const override final;
- ParamType *handle_substitions (SubstitutionArgumentMappings mappings);
+ ParamType *handle_substitions (SubstitutionArgumentMappings &mappings);
private:
std::string symbol;
@@ -460,31 +306,25 @@ private:
class StructFieldType
{
public:
- StructFieldType (HirId ref, std::string name, BaseType *ty, Location locus)
- : ref (ref), name (name), ty (ty), locus (locus)
- {}
+ StructFieldType (HirId ref, std::string name, BaseType *ty, Location locus);
- HirId get_ref () const { return ref; }
-
- std::string as_string () const;
+ HirId get_ref () const;
bool is_equal (const StructFieldType &other) const;
- std::string get_name () const { return name; }
-
- BaseType *get_field_type () const { return ty; }
+ std::string get_name () const;
- void set_field_type (BaseType *fty) { ty = fty; }
+ BaseType *get_field_type () const;
+ void set_field_type (BaseType *fty);
StructFieldType *clone () const;
-
StructFieldType *monomorphized_clone () const;
- bool is_concrete () const { return ty->is_concrete (); }
-
- void debug () const { rust_debug ("%s", as_string ().c_str ()); }
+ bool is_concrete () const;
- Location get_locus () const { return locus; }
+ void debug () const;
+ Location get_locus () const;
+ std::string as_string () const;
private:
HirId ref;
@@ -498,527 +338,44 @@ class TupleType : public BaseType
public:
TupleType (HirId ref, Location locus,
std::vector<TyVar> fields = std::vector<TyVar> (),
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::TUPLE,
- {Resolver::CanonicalPath::create_empty (), locus}, refs),
- fields (fields)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
TupleType (HirId ref, HirId ty_ref, Location locus,
std::vector<TyVar> fields = std::vector<TyVar> (),
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::TUPLE,
- {Resolver::CanonicalPath::create_empty (), locus}, refs),
- fields (fields)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
- static TupleType *get_unit_type (HirId ref)
- {
- return new TupleType (ref, Linemap::predeclared_location ());
- }
+ static TupleType *get_unit_type (HirId ref);
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
- bool is_unit () const override { return this->fields.empty (); }
+ bool is_unit () const override;
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;
- size_t num_fields () const { return fields.size (); }
+ size_t num_fields () const;
BaseType *get_field (size_t index) const;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- bool is_concrete () const override final
- {
- for (size_t i = 0; i < num_fields (); i++)
- {
- if (!get_field (i)->is_concrete ())
- return false;
- }
- return true;
- }
+ bool is_concrete () const override final;
- const std::vector<TyVar> &get_fields () const { return fields; }
+ const std::vector<TyVar> &get_fields () const;
std::string get_name () const override final;
- TupleType *handle_substitions (SubstitutionArgumentMappings mappings);
+ TupleType *handle_substitions (SubstitutionArgumentMappings &mappings);
private:
std::vector<TyVar> fields;
};
-class SubstitutionParamMapping
-{
-public:
- SubstitutionParamMapping (const HIR::TypeParam &generic, ParamType *param)
- : generic (generic), param (param)
- {}
-
- SubstitutionParamMapping (const SubstitutionParamMapping &other)
- : generic (other.generic), param (other.param)
- {}
-
- std::string as_string () const
- {
- if (param == nullptr)
- return "nullptr";
-
- return param->get_name ();
- }
-
- bool fill_param_ty (SubstitutionArgumentMappings &subst_mappings,
- Location locus);
-
- SubstitutionParamMapping clone () const
- {
- return SubstitutionParamMapping (generic, static_cast<ParamType *> (
- param->clone ()));
- }
-
- ParamType *get_param_ty () { return param; }
-
- const ParamType *get_param_ty () const { return param; }
-
- const HIR::TypeParam &get_generic_param () { return generic; };
-
- // this is used for the backend to override the HirId ref of the param to
- // what the concrete type is for the rest of the context
- void override_context ();
-
- bool needs_substitution () const
- {
- return !(get_param_ty ()->is_concrete ());
- }
-
- Location get_param_locus () const { return generic.get_locus (); }
-
- bool param_has_default_ty () const { return generic.has_type (); }
-
- BaseType *get_default_ty () const
- {
- TyVar var (generic.get_type_mappings ().get_hirid ());
- return var.get_tyty ();
- }
-
- bool need_substitution () const;
-
-private:
- const HIR::TypeParam &generic;
- ParamType *param;
-};
-
-class SubstitutionArg
-{
-public:
- SubstitutionArg (const SubstitutionParamMapping *param, BaseType *argument)
- : param (param), argument (argument)
- {}
-
- // FIXME
- // the copy constructors need removed - they are unsafe see
- // TypeBoundPredicate
- SubstitutionArg (const SubstitutionArg &other)
- : param (other.param), argument (other.argument)
- {}
-
- SubstitutionArg &operator= (const SubstitutionArg &other)
- {
- param = other.param;
- argument = other.argument;
- return *this;
- }
-
- BaseType *get_tyty () { return argument; }
-
- const BaseType *get_tyty () const { return argument; }
-
- const SubstitutionParamMapping *get_param_mapping () const { return param; }
-
- static SubstitutionArg error () { return SubstitutionArg (nullptr, nullptr); }
-
- bool is_error () const { return param == nullptr || argument == nullptr; }
-
- bool is_conrete () const
- {
- if (argument != nullptr)
- return true;
-
- if (argument->get_kind () == TyTy::TypeKind::PARAM)
- return false;
-
- return argument->is_concrete ();
- }
-
- std::string as_string () const
- {
- return param->as_string ()
- + (argument != nullptr ? ":" + argument->as_string () : "");
- }
-
-private:
- const SubstitutionParamMapping *param;
- BaseType *argument;
-};
-
-typedef std::function<void (const ParamType &, const SubstitutionArg &)>
- ParamSubstCb;
-class SubstitutionArgumentMappings
-{
-public:
- SubstitutionArgumentMappings (std::vector<SubstitutionArg> mappings,
- std::map<std::string, BaseType *> binding_args,
- Location locus,
- ParamSubstCb param_subst_cb = nullptr,
- bool trait_item_flag = false)
- : mappings (mappings), binding_args (binding_args), locus (locus),
- param_subst_cb (param_subst_cb), trait_item_flag (trait_item_flag)
- {}
-
- SubstitutionArgumentMappings (const SubstitutionArgumentMappings &other)
- : mappings (other.mappings), binding_args (other.binding_args),
- locus (other.locus), param_subst_cb (other.param_subst_cb),
- trait_item_flag (other.trait_item_flag)
- {}
-
- SubstitutionArgumentMappings &
- operator= (const SubstitutionArgumentMappings &other)
- {
- mappings = other.mappings;
- binding_args = other.binding_args;
- locus = other.locus;
- param_subst_cb = other.param_subst_cb;
- trait_item_flag = other.trait_item_flag;
-
- return *this;
- }
-
- SubstitutionArgumentMappings (SubstitutionArgumentMappings &&other) = default;
- SubstitutionArgumentMappings &operator= (SubstitutionArgumentMappings &&other)
- = default;
-
- static SubstitutionArgumentMappings error ()
- {
- return SubstitutionArgumentMappings ({}, {}, Location (), nullptr, false);
- }
-
- bool is_error () const { return mappings.size () == 0; }
-
- bool get_argument_for_symbol (const ParamType *param_to_find,
- SubstitutionArg *argument)
- {
- for (auto &mapping : mappings)
- {
- const SubstitutionParamMapping *param = mapping.get_param_mapping ();
- const ParamType *p = param->get_param_ty ();
-
- if (p->get_symbol ().compare (param_to_find->get_symbol ()) == 0)
- {
- *argument = mapping;
- return true;
- }
- }
- return false;
- }
-
- bool get_argument_at (size_t index, SubstitutionArg *argument)
- {
- if (index > mappings.size ())
- return false;
-
- *argument = mappings.at (index);
- return true;
- }
-
- // is_concrete means if the used args is non error, ie: non empty this will
- // verify if actual real types have been put in place of are they still
- // ParamTy
- bool is_concrete () const
- {
- for (auto &mapping : mappings)
- {
- if (!mapping.is_conrete ())
- return false;
- }
- return true;
- }
-
- Location get_locus () const { return locus; }
-
- size_t size () const { return mappings.size (); }
-
- bool is_empty () const { return size () == 0; }
-
- std::vector<SubstitutionArg> &get_mappings () { return mappings; }
-
- const std::vector<SubstitutionArg> &get_mappings () const { return mappings; }
-
- std::map<std::string, BaseType *> &get_binding_args ()
- {
- return binding_args;
- }
-
- const std::map<std::string, BaseType *> &get_binding_args () const
- {
- return binding_args;
- }
-
- std::string as_string () const
- {
- std::string buffer;
- for (auto &mapping : mappings)
- {
- buffer += mapping.as_string () + ", ";
- }
- return "<" + buffer + ">";
- }
-
- void on_param_subst (const ParamType &p, const SubstitutionArg &a) const
- {
- if (param_subst_cb == nullptr)
- return;
-
- param_subst_cb (p, a);
- }
-
- ParamSubstCb get_subst_cb () const { return param_subst_cb; }
-
- bool trait_item_mode () const { return trait_item_flag; }
-
-private:
- std::vector<SubstitutionArg> mappings;
- std::map<std::string, BaseType *> binding_args;
- Location locus;
- ParamSubstCb param_subst_cb;
- bool trait_item_flag;
-};
-
-class SubstitutionRef
-{
-public:
- SubstitutionRef (std::vector<SubstitutionParamMapping> substitutions,
- SubstitutionArgumentMappings arguments)
- : substitutions (substitutions), used_arguments (arguments)
- {}
-
- bool has_substitutions () const { return substitutions.size () > 0; }
-
- std::string subst_as_string () const
- {
- std::string buffer;
- for (size_t i = 0; i < substitutions.size (); i++)
- {
- const SubstitutionParamMapping &sub = substitutions.at (i);
- buffer += sub.as_string ();
-
- if ((i + 1) < substitutions.size ())
- buffer += ", ";
- }
-
- return buffer.empty () ? "" : "<" + buffer + ">";
- }
-
- bool supports_associated_bindings () const
- {
- return get_num_associated_bindings () > 0;
- }
-
- // this is overridden in TypeBoundPredicate
- // which support bindings we don't add them directly to the SubstitutionRef
- // base class because this class represents the fn<X: Foo, Y: Bar>. The only
- // construct which supports associated types
- virtual size_t get_num_associated_bindings () const { return 0; }
-
- // this is overridden in TypeBoundPredicate
- virtual TypeBoundPredicateItem
- lookup_associated_type (const std::string &search)
- {
- return TypeBoundPredicateItem::error ();
- }
-
- size_t get_num_substitutions () const { return substitutions.size (); }
-
- std::vector<SubstitutionParamMapping> &get_substs () { return substitutions; }
-
- const std::vector<SubstitutionParamMapping> &get_substs () const
- {
- return substitutions;
- }
-
- std::vector<SubstitutionParamMapping> clone_substs () const
- {
- std::vector<SubstitutionParamMapping> clone;
-
- for (auto &sub : substitutions)
- clone.push_back (sub.clone ());
-
- return clone;
- }
-
- void override_context ()
- {
- for (auto &sub : substitutions)
- {
- sub.override_context ();
- }
- }
-
- bool needs_substitution () const
- {
- for (auto &sub : substitutions)
- {
- if (sub.need_substitution ())
- return true;
- }
- return false;
- }
-
- bool was_substituted () const { return !needs_substitution (); }
-
- SubstitutionArgumentMappings get_substitution_arguments () const
- {
- return used_arguments;
- }
-
- // this is the count of type params that are not substituted fuly
- size_t num_required_substitutions () const
- {
- size_t n = 0;
- for (auto &p : substitutions)
- {
- if (p.needs_substitution ())
- n++;
- }
- return n;
- }
-
- // this is the count of type params that need substituted taking into account
- // possible defaults
- size_t min_required_substitutions () const
- {
- size_t n = 0;
- for (auto &p : substitutions)
- {
- if (p.needs_substitution () && !p.param_has_default_ty ())
- n++;
- }
- return n;
- }
-
- // We are trying to subst <i32, f32> into Struct Foo<X,Y> {}
- // in the case of Foo<i32,f32>{...}
- //
- // the substitions we have here define X,Y but the arguments have no bindings
- // so its a matter of ordering
- SubstitutionArgumentMappings
- get_mappings_from_generic_args (HIR::GenericArgs &args);
-
- // Recursive substitutions
- // Foo <A,B> { a:A, b: B}; Bar <X,Y,Z>{a:X, b: Foo<Y,Z>}
- //
- // we have bindings for X Y Z and need to propagate the binding Y,Z into Foo
- // Which binds to A,B
- SubstitutionArgumentMappings
- adjust_mappings_for_this (SubstitutionArgumentMappings &mappings);
-
- // Are the mappings here actually bound to this type. For example imagine the
- // case:
- //
- // struct Foo<T>(T);
- // impl<T> Foo<T> {
- // fn test(self) { ... }
- // }
- //
- // In this case we have a generic ADT of Foo and an impl block of a generic T
- // on Foo for the Self type. When we it comes to path resolution we can have:
- //
- // Foo::<i32>::test()
- //
- // This means the first segment of Foo::<i32> returns the ADT Foo<i32> not the
- // Self ADT bound to the T from the impl block. This means when it comes to
- // the next segment of test which resolves to the function we need to check
- // wether the arguments in the struct definition of foo can be bound here
- // before substituting the previous segments type here. This functions acts as
- // a guard for the solve_mappings_from_receiver_for_self to handle the case
- // where arguments are not bound. This is important for this next case:
- //
- // struct Baz<A, B>(A, B);
- // impl Baz<i32, f32> {
- // fn test<X>(a: X) -> X {
- // a
- // }
- // }
- //
- // In this case Baz has been already substituted for the impl's Self to become
- // ADT<i32, f32> so that the function test only has 1 generic argument of X.
- // The path for this will be:
- //
- // Baz::test::<_>(123)
- //
- // So the first segment here will be Baz<_, _> to try and infer the arguments
- // which will be taken from the impl's Self type in this case since it is
- // already substituted and like the previous case the check to see if we need
- // to inherit the previous segments generic arguments takes place but the
- // generic arguments are not bound to this type as they have already been
- // substituted.
- //
- // Its important to remember from the first example the FnType actually looks
- // like:
- //
- // fn <T>test(self :Foo<T>(T))
- //
- // As the generic parameters are "bound" to each of the items in the impl
- // block. So this check is about wether the arguments we have here can
- // actually be bound to this type.
- bool are_mappings_bound (SubstitutionArgumentMappings &mappings);
-
- // struct Foo<A, B>(A, B);
- //
- // impl<T> Foo<T, f32>;
- // -> fn test<X>(self, a: X) -> X
- //
- // We might invoke this via:
- //
- // a = Foo(123, 456f32);
- // b = a.test::<bool>(false);
- //
- // we need to figure out relevant generic arguemts for self to apply to the
- // fntype
- SubstitutionArgumentMappings solve_mappings_from_receiver_for_self (
- SubstitutionArgumentMappings &mappings) const;
-
- // TODO comment
- SubstitutionArgumentMappings
- solve_missing_mappings_from_this (SubstitutionRef &ref, SubstitutionRef &to);
-
- // TODO comment
- BaseType *infer_substitions (Location locus);
-
- // TODO comment
- bool monomorphize ();
-
- // TODO comment
- virtual BaseType *handle_substitions (SubstitutionArgumentMappings mappings)
- = 0;
-
- SubstitutionArgumentMappings get_used_arguments () const
- {
- return used_arguments;
- }
-
-protected:
- std::vector<SubstitutionParamMapping> substitutions;
- SubstitutionArgumentMappings used_arguments;
-};
-
class TypeBoundPredicate : public SubstitutionRef
{
public:
@@ -1061,7 +418,7 @@ public:
// WARNING THIS WILL ALWAYS RETURN NULLPTR
BaseType *
- handle_substitions (SubstitutionArgumentMappings mappings) override final;
+ handle_substitions (SubstitutionArgumentMappings &mappings) override final;
bool is_error () const;
@@ -1095,185 +452,48 @@ public:
STRUCT
};
- static std::string variant_type_string (VariantType type)
- {
- switch (type)
- {
- case NUM:
- return "enumeral";
- case TUPLE:
- return "tuple";
- case STRUCT:
- return "struct";
- }
- gcc_unreachable ();
- return "";
- }
+ static std::string variant_type_string (VariantType type);
VariantDef (HirId id, DefId defid, std::string identifier, RustIdent ident,
- HIR::Expr *discriminant)
- : id (id), defid (defid), identifier (identifier), ident (ident),
- discriminant (discriminant)
-
- {
- type = VariantType::NUM;
- fields = {};
- }
+ HIR::Expr *discriminant);
VariantDef (HirId id, DefId defid, std::string identifier, RustIdent ident,
VariantType type, HIR::Expr *discriminant,
- std::vector<StructFieldType *> fields)
- : id (id), defid (defid), identifier (identifier), ident (ident),
- type (type), discriminant (discriminant), fields (fields)
- {
- rust_assert (
- (type == VariantType::NUM && fields.empty ())
- || (type == VariantType::TUPLE || type == VariantType::STRUCT));
- }
+ std::vector<StructFieldType *> fields);
- VariantDef (const VariantDef &other)
- : id (other.id), defid (other.defid), identifier (other.identifier),
- ident (other.ident), type (other.type), discriminant (other.discriminant),
- fields (other.fields)
- {}
+ VariantDef (const VariantDef &other);
- VariantDef &operator= (const VariantDef &other)
- {
- id = other.id;
- identifier = other.identifier;
- type = other.type;
- discriminant = other.discriminant;
- fields = other.fields;
- ident = other.ident;
-
- return *this;
- }
+ VariantDef &operator= (const VariantDef &other);
- static VariantDef &get_error_node ()
- {
- static VariantDef node
- = VariantDef (UNKNOWN_HIRID, UNKNOWN_DEFID, "",
- {Resolver::CanonicalPath::create_empty (),
- Linemap::unknown_location ()},
- nullptr);
+ static VariantDef &get_error_node ();
+ bool is_error () const;
- return node;
- }
+ HirId get_id () const;
+ DefId get_defid () const;
- bool is_error () const { return get_id () == UNKNOWN_HIRID; }
+ VariantType get_variant_type () const;
+ bool is_data_variant () const;
+ bool is_dataless_variant () const;
- HirId get_id () const { return id; }
- DefId get_defid () const { return defid; }
+ std::string get_identifier () const;
- VariantType get_variant_type () const { return type; }
- bool is_data_variant () const { return type != VariantType::NUM; }
- bool is_dataless_variant () const { return type == VariantType::NUM; }
+ size_t num_fields () const;
+ StructFieldType *get_field_at_index (size_t index);
- std::string get_identifier () const { return identifier; }
-
- size_t num_fields () const { return fields.size (); }
- StructFieldType *get_field_at_index (size_t index)
- {
- rust_assert (index < fields.size ());
- return fields.at (index);
- }
-
- std::vector<StructFieldType *> &get_fields ()
- {
- rust_assert (type != NUM);
- return fields;
- }
+ std::vector<StructFieldType *> &get_fields ();
bool lookup_field (const std::string &lookup, StructFieldType **field_lookup,
- size_t *index) const
- {
- size_t i = 0;
- for (auto &field : fields)
- {
- if (field->get_name ().compare (lookup) == 0)
- {
- if (index != nullptr)
- *index = i;
+ size_t *index) const;
- if (field_lookup != nullptr)
- *field_lookup = field;
+ HIR::Expr *get_discriminant () const;
- return true;
- }
- i++;
- }
- return false;
- }
-
- HIR::Expr *get_discriminant () const
- {
- rust_assert (discriminant != nullptr);
- return discriminant;
- }
-
- std::string as_string () const
- {
- if (type == VariantType::NUM)
- return identifier + " = " + discriminant->as_string ();
-
- std::string buffer;
- for (size_t i = 0; i < fields.size (); ++i)
- {
- buffer += fields.at (i)->as_string ();
- if ((i + 1) < fields.size ())
- buffer += ", ";
- }
-
- if (type == VariantType::TUPLE)
- return identifier + " (" + buffer + ")";
- else
- return identifier + " {" + buffer + "}";
- }
-
- bool is_equal (const VariantDef &other) const
- {
- if (type != other.type)
- return false;
-
- if (identifier.compare (other.identifier) != 0)
- return false;
-
- if (discriminant != other.discriminant)
- return false;
-
- if (fields.size () != other.fields.size ())
- return false;
-
- for (size_t i = 0; i < fields.size (); i++)
- {
- if (!fields.at (i)->is_equal (*other.fields.at (i)))
- return false;
- }
-
- return true;
- }
-
- VariantDef *clone () const
- {
- std::vector<StructFieldType *> cloned_fields;
- for (auto &f : fields)
- cloned_fields.push_back ((StructFieldType *) f->clone ());
-
- return new VariantDef (id, defid, identifier, ident, type, discriminant,
- cloned_fields);
- }
-
- VariantDef *monomorphized_clone () const
- {
- std::vector<StructFieldType *> cloned_fields;
- for (auto &f : fields)
- cloned_fields.push_back ((StructFieldType *) f->monomorphized_clone ());
+ std::string as_string () const;
- return new VariantDef (id, defid, identifier, ident, type, discriminant,
- cloned_fields);
- }
+ bool is_equal (const VariantDef &other) const;
+ VariantDef *clone () const;
+ VariantDef *monomorphized_clone () const;
- const RustIdent &get_ident () const { return ident; }
+ const RustIdent &get_ident () const;
private:
HirId id;
@@ -1369,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;
@@ -1453,7 +672,7 @@ public:
}
ADTType *
- handle_substitions (SubstitutionArgumentMappings mappings) override final;
+ handle_substitions (SubstitutionArgumentMappings &mappings) override final;
private:
std::string identifier;
@@ -1509,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;
@@ -1586,7 +804,7 @@ public:
}
FnType *
- handle_substitions (SubstitutionArgumentMappings mappings) override final;
+ handle_substitions (SubstitutionArgumentMappings &mappings) override final;
ABI get_abi () const { return abi; }
@@ -1629,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;
@@ -1709,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;
@@ -1736,7 +952,7 @@ public:
}
ClosureType *
- handle_substitions (SubstitutionArgumentMappings mappings) override final;
+ handle_substitions (SubstitutionArgumentMappings &mappings) override final;
TyTy::TupleType &get_parameters () const { return *parameters; }
TyTy::BaseType &get_result_type () const { return *result_type.get_tyty (); }
@@ -1778,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;
@@ -1795,7 +1010,7 @@ public:
HIR::Expr &get_capacity_expr () const { return capacity_expr; }
- ArrayType *handle_substitions (SubstitutionArgumentMappings mappings);
+ ArrayType *handle_substitions (SubstitutionArgumentMappings &mappings);
private:
TyVar element_type;
@@ -1826,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;
@@ -1841,7 +1055,7 @@ public:
return get_element_type ()->is_concrete ();
}
- SliceType *handle_substitions (SubstitutionArgumentMappings mappings);
+ SliceType *handle_substitions (SubstitutionArgumentMappings &mappings);
private:
TyVar element_type;
@@ -1850,33 +1064,21 @@ private:
class BoolType : public BaseType
{
public:
- BoolType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::BOOL,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
-
- BoolType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::BOOL,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
+ BoolType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+ BoolType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
- std::string get_name () const override final { return as_string (); }
+ 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;
BaseType *monomorphized_clone () const final override;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
};
class IntType : public BaseType
@@ -1891,40 +1093,26 @@ public:
I128
};
- IntType (HirId ref, IntKind kind, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::INT,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- int_kind (kind)
- {}
-
+ IntType (HirId ref, IntKind kind, std::set<HirId> refs = std::set<HirId> ());
IntType (HirId ref, HirId ty_ref, IntKind kind,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::INT,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- int_kind (kind)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
- std::string get_name () const override final { return as_string (); }
+ 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 { return int_kind; }
+ IntKind get_int_kind () const;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
bool is_equal (const BaseType &other) const override;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
private:
IntKind int_kind;
@@ -1942,40 +1130,27 @@ public:
U128
};
- UintType (HirId ref, UintKind kind, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::UINT,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- uint_kind (kind)
- {}
-
+ UintType (HirId ref, UintKind kind,
+ std::set<HirId> refs = std::set<HirId> ());
UintType (HirId ref, HirId ty_ref, UintKind kind,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::UINT,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- uint_kind (kind)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
- std::string get_name () const override final { return as_string (); }
+ 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 { return uint_kind; }
+ UintKind get_uint_kind () const;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
bool is_equal (const BaseType &other) const override;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
private:
UintKind uint_kind;
@@ -1991,40 +1166,25 @@ public:
};
FloatType (HirId ref, FloatKind kind,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::FLOAT,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- float_kind (kind)
- {}
-
+ std::set<HirId> refs = std::set<HirId> ());
FloatType (HirId ref, HirId ty_ref, FloatKind kind,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::FLOAT,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- float_kind (kind)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
+ std::string get_name () const override final;
- 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;
- FloatKind get_float_kind () const { return float_kind; }
+ FloatKind get_float_kind () const;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
bool is_equal (const BaseType &other) const override;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
private:
FloatKind float_kind;
@@ -2033,153 +1193,91 @@ private:
class USizeType : public BaseType
{
public:
- USizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::USIZE,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
-
- USizeType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::USIZE,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
+ USizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+ USizeType (HirId ref, HirId ty_ref,
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
+ std::string get_name () const override final;
- 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;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
};
class ISizeType : public BaseType
{
public:
- ISizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::ISIZE,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
-
- ISizeType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::ISIZE,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
+ ISizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+ ISizeType (HirId ref, HirId ty_ref,
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
+ std::string get_name () const override final;
- 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;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
};
class CharType : public BaseType
{
public:
- CharType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::CHAR,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
-
- CharType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::CHAR,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
+ CharType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+ CharType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
+ std::string get_name () const override final;
- 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;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
};
class StrType : public BaseType
{
public:
- StrType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::STR,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
+ StrType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+ StrType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ());
- StrType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::STR,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
-
- std::string get_name () const override final { return as_string (); }
+ std::string get_name () const override final;
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
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;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
};
class ReferenceType : public BaseType
{
public:
ReferenceType (HirId ref, TyVar base, Mutability mut,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::REF,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- base (base), mut (mut)
- {}
-
+ std::set<HirId> refs = std::set<HirId> ());
ReferenceType (HirId ref, HirId ty_ref, TyVar base, Mutability mut,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::REF,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- base (base), mut (mut)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
BaseType *get_base () const;
@@ -2190,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;
@@ -2198,45 +1295,19 @@ public:
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- bool is_concrete () const override final
- {
- return get_base ()->is_concrete ();
- }
+ bool is_concrete () const override final;
- ReferenceType *handle_substitions (SubstitutionArgumentMappings mappings);
+ ReferenceType *handle_substitions (SubstitutionArgumentMappings &mappings);
- Mutability mutability () const { return mut; }
+ Mutability mutability () const;
- bool is_mutable () const { return mut == Mutability::Mut; }
+ bool is_mutable () const;
- bool is_dyn_object () const
- {
- return is_dyn_slice_type () || is_dyn_str_type ();
- }
+ bool is_dyn_object () const;
- bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const
- {
- const TyTy::BaseType *element = get_base ()->destructure ();
- if (element->get_kind () != TyTy::TypeKind::SLICE)
- return false;
- if (slice == nullptr)
- return true;
+ bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const;
- *slice = static_cast<const TyTy::SliceType *> (element);
- return true;
- }
-
- bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const
- {
- const TyTy::BaseType *element = get_base ()->destructure ();
- if (element->get_kind () != TyTy::TypeKind::STR)
- return false;
- if (str == nullptr)
- return true;
-
- *str = static_cast<const TyTy::StrType *> (element);
- return true;
- }
+ bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const;
private:
TyVar base;
@@ -2247,22 +1318,9 @@ class PointerType : public BaseType
{
public:
PointerType (HirId ref, TyVar base, Mutability mut,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::POINTER,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- base (base), mut (mut)
- {}
-
+ std::set<HirId> refs = std::set<HirId> ());
PointerType (HirId ref, HirId ty_ref, TyVar base, Mutability mut,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::POINTER,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- base (base), mut (mut)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
BaseType *get_base () const;
@@ -2272,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;
@@ -2280,47 +1337,17 @@ public:
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- bool is_concrete () const override final
- {
- return get_base ()->is_concrete ();
- }
-
- PointerType *handle_substitions (SubstitutionArgumentMappings mappings);
-
- Mutability mutability () const { return mut; }
-
- bool is_mutable () const { return mut == Mutability::Mut; }
-
- bool is_const () const { return mut == Mutability::Imm; }
-
- bool is_dyn_object () const
- {
- return is_dyn_slice_type () || is_dyn_str_type ();
- }
-
- bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const
- {
- const TyTy::BaseType *element = get_base ()->destructure ();
- if (element->get_kind () != TyTy::TypeKind::SLICE)
- return false;
- if (slice == nullptr)
- return true;
+ bool is_concrete () const override final;
- *slice = static_cast<const TyTy::SliceType *> (element);
- return true;
- }
+ PointerType *handle_substitions (SubstitutionArgumentMappings &mappings);
- bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const
- {
- const TyTy::BaseType *element = get_base ()->destructure ();
- if (element->get_kind () != TyTy::TypeKind::STR)
- return false;
- if (str == nullptr)
- return true;
+ Mutability mutability () const;
+ bool is_mutable () const;
+ bool is_const () const;
+ bool is_dyn_object () const;
- *str = static_cast<const TyTy::StrType *> (element);
- return true;
- }
+ bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const;
+ bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const;
private:
TyVar base;
@@ -2340,35 +1367,24 @@ private:
class NeverType : public BaseType
{
public:
- NeverType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::NEVER,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
-
- NeverType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::NEVER,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
+ NeverType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+ NeverType (HirId ref, HirId ty_ref,
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
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;
BaseType *monomorphized_clone () const final override;
- std::string get_name () const override final { return as_string (); }
+ std::string get_name () const override final;
- bool is_unit () const override { return true; }
- bool is_concrete () const override final { return true; }
+ bool is_unit () const override;
+ bool is_concrete () const override final;
};
// used at the type in associated types in traits
@@ -2377,43 +1393,25 @@ class PlaceholderType : public BaseType
{
public:
PlaceholderType (std::string symbol, HirId ref,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::PLACEHOLDER,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- symbol (symbol)
- {}
-
+ std::set<HirId> refs = std::set<HirId> ());
PlaceholderType (std::string symbol, HirId ref, HirId ty_ref,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::PLACEHOLDER,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- symbol (symbol)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
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;
BaseType *monomorphized_clone () const final override;
- std::string get_name () const override final { return as_string (); }
+ std::string get_name () const override final;
- bool is_unit () const override
- {
- rust_assert (can_resolve ());
- return resolve ()->is_unit ();
- }
+ bool is_unit () const override;
- std::string get_symbol () const { return symbol; }
+ std::string get_symbol () const;
void set_associated_type (HirId ref);
@@ -2425,13 +1423,7 @@ public:
bool is_equal (const BaseType &other) const override;
- bool is_concrete () const override final
- {
- if (!can_resolve ())
- return true;
-
- return resolve ()->is_concrete ();
- }
+ bool is_concrete () const override final;
private:
std::string symbol;
@@ -2445,63 +1437,42 @@ public:
std::vector<SubstitutionParamMapping> subst_refs,
SubstitutionArgumentMappings generic_arguments
= SubstitutionArgumentMappings::error (),
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::PROJECTION,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
- base (base), trait (trait), item (item)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
ProjectionType (HirId ref, HirId ty_ref, BaseType *base,
const Resolver::TraitReference *trait, DefId item,
std::vector<SubstitutionParamMapping> subst_refs,
SubstitutionArgumentMappings generic_arguments
= SubstitutionArgumentMappings::error (),
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::PROJECTION,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
- base (base), trait (trait), item (item)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
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;
BaseType *monomorphized_clone () const final override;
- std::string get_name () const override final { return as_string (); }
+ std::string get_name () const override final;
- bool is_unit () const override { return false; }
+ bool is_unit () const override;
- bool needs_generic_substitutions () const override final
- {
- return needs_substitution ();
- }
+ bool needs_generic_substitutions () const override final;
- bool supports_substitutions () const override final { return true; }
+ bool supports_substitutions () const override final;
- bool has_subsititions_defined () const override final
- {
- return has_substitutions ();
- }
+ bool has_subsititions_defined () const override final;
- const BaseType *get () const { return base; }
- BaseType *get () { return base; }
+ const BaseType *get () const;
+ BaseType *get ();
- bool is_concrete () const override final { return base->is_concrete (); }
+ bool is_concrete () const override final;
ProjectionType *
- handle_substitions (SubstitutionArgumentMappings mappings) override final;
+ handle_substitions (SubstitutionArgumentMappings &mappings) override final;
private:
BaseType *base;
@@ -2514,22 +1485,17 @@ class DynamicObjectType : public BaseType
public:
DynamicObjectType (HirId ref, RustIdent ident,
std::vector<TypeBoundPredicate> specified_bounds,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
DynamicObjectType (HirId ref, HirId ty_ref, RustIdent ident,
std::vector<TypeBoundPredicate> specified_bounds,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
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;
@@ -2539,7 +1505,7 @@ public:
std::string get_name () const override final;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
// this returns a flat list of items including super trait bounds
const std::vector<
diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
new file mode 100644
index 0000000..415ffcd
--- /dev/null
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -0,0 +1,1651 @@
+// 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 ());
+
+ // check bounds
+ if (ltype->num_specified_bounds () > 0)
+ {
+ if (!ltype->bounds_compatible (*rtype, locus, true))
+ {
+ // already emitted an error
+ emit_error = false;
+ return new TyTy::ErrorType (0);
+ }
+ }
+
+ 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 (
+ &ltype->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 (&ltype->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
diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h
new file mode 100644
index 0000000..6e46b96
--- /dev/null
+++ b/gcc/rust/typecheck/rust-unify.h
@@ -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
diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h
index 52f53fa..5bad08a 100644
--- a/gcc/rust/util/rust-lang-item.h
+++ b/gcc/rust/util/rust-lang-item.h
@@ -80,6 +80,12 @@ public:
FN_ONCE,
FN_ONCE_OUTPUT,
+ // markers
+ COPY,
+ CLONE,
+ SIZED,
+
+ // delimiter
UNKNOWN,
};
@@ -237,6 +243,18 @@ public:
{
return ItemType::FN_ONCE_OUTPUT;
}
+ else if (item.compare ("copy") == 0)
+ {
+ return ItemType::COPY;
+ }
+ else if (item.compare ("clone") == 0)
+ {
+ return ItemType::CLONE;
+ }
+ else if (item.compare ("sized") == 0)
+ {
+ return ItemType::SIZED;
+ }
return ItemType::UNKNOWN;
}
@@ -321,6 +339,12 @@ public:
return "fn_once";
case FN_ONCE_OUTPUT:
return "fn_once_output";
+ case COPY:
+ return "copy";
+ case CLONE:
+ return "clone";
+ case SIZED:
+ return "sized";
case UNKNOWN:
return "<UNKNOWN>";
diff --git a/gcc/testsuite/rust/bounds1.rs b/gcc/testsuite/rust/bounds1.rs
new file mode 100644
index 0000000..6658360
--- /dev/null
+++ b/gcc/testsuite/rust/bounds1.rs
@@ -0,0 +1,19 @@
+mod core {
+ mod ops {
+ #[lang = "add"]
+ pub trait Add<Rhs = Self> {
+ type Output;
+
+ fn add(self, rhs: Rhs) -> Self::Output;
+ }
+ }
+}
+
+pub fn foo<T: core::ops::Add<Output = i32>>(a: T) -> i32 {
+ // { dg-error "bounds not satisfied for f32 .Add. is not satisfied" "" { target *-*-* } .-1 }
+ a + a
+}
+
+pub fn main() {
+ foo(123f32);
+}
diff --git a/gcc/testsuite/rust/compile/func3.rs b/gcc/testsuite/rust/compile/func3.rs
index 2a32947..002e5c9 100644
--- a/gcc/testsuite/rust/compile/func3.rs
+++ b/gcc/testsuite/rust/compile/func3.rs
@@ -5,5 +5,4 @@ fn test(a: i32, b: i32) -> i32 {
fn main() {
let a = test(1, true);
// { dg-error "expected .i32. got .bool." "" { target *-*-* } .-1 }
- // { dg-error "Type Resolution failure on parameter" "" { target *-*-* } .-2 }
}
diff --git a/gcc/testsuite/rust/compile/issue-1773.rs b/gcc/testsuite/rust/compile/issue-1773.rs
new file mode 100644
index 0000000..c627ac0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1773.rs
@@ -0,0 +1,20 @@
+trait Foo<T> {
+ type A;
+
+ fn test(a: Self::A) -> Self::A {
+ a
+ }
+}
+
+struct Bar<T>(T);
+impl<T> Foo<T> for Bar<i32> {
+ type A = T;
+}
+
+fn main() {
+ let a;
+ a = Bar(123);
+
+ let b;
+ b = Bar::test(a.0);
+}
diff --git a/gcc/testsuite/rust/compile/issue-1786.rs b/gcc/testsuite/rust/compile/issue-1786.rs
new file mode 100644
index 0000000..f73b63d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1786.rs
@@ -0,0 +1,23 @@
+#[lang = "clone"]
+trait Clone {
+ fn clone(&self) -> Self;
+
+ fn clone_from(&mut self, source: &Self) {
+ *self = source.clone()
+ }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+ // Empty.
+}
+
+mod impls {
+ use super::Clone;
+
+ impl Clone for char {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+}
diff --git a/gcc/testsuite/rust/compile/never_type_err1.rs b/gcc/testsuite/rust/compile/never_type1.rs
index 52b1283..8d56176 100644
--- a/gcc/testsuite/rust/compile/never_type_err1.rs
+++ b/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;
diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-4.rs b/gcc/testsuite/rust/compile/torture/intrinsics-4.rs
index 243d446..4e09f10 100644
--- a/gcc/testsuite/rust/compile/torture/intrinsics-4.rs
+++ b/gcc/testsuite/rust/compile/torture/intrinsics-4.rs
@@ -1,10 +1,67 @@
-trait Copy {}
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+ fn clone(&self) -> Self;
+
+ fn clone_from(&mut self, source: &Self) {
+ *self = source.clone()
+ }
+}
+
+mod impls {
+ use super::Clone;
+
+ macro_rules! impl_clone {
+ ($($t:ty)*) => {
+ $(
+ impl Clone for $t {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+ )*
+ }
+ }
+
+ impl_clone! {
+ usize u8 u16 u32 u64 // u128
+ isize i8 i16 i32 i64 // i128
+ f32 f64
+ bool char
+ }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+ // Empty.
+}
+
+mod copy_impls {
+ use super::Copy;
+
+ macro_rules! impl_copy {
+ ($($t:ty)*) => {
+ $(
+ impl Copy for $t {}
+ )*
+ }
+ }
+
+ impl_copy! {
+ usize u8 u16 u32 u64 // u128
+ isize i8 i16 i32 i64 // i128
+ f32 f64
+ bool char
+ }
+}
extern "rust-intrinsic" {
pub fn atomic_store_seqcst<T: Copy>(dst: *mut T, val: T);
pub fn atomic_store_release<T: Copy>(dst: *mut T, val: T);
pub fn atomic_store_relaxed<T: Copy>(dst: *mut T, val: T);
- // pub fn atomic_store_unordered<T: Copy>(dst: *mut T, val: T);
+ pub fn atomic_store_unordered<T: Copy>(dst: *mut T, val: T);
}
fn main() {
@@ -15,6 +72,6 @@ fn main() {
atomic_store_seqcst(&mut dst, new_value);
atomic_store_release(&mut dst, new_value);
atomic_store_relaxed(&mut dst, new_value);
- // atomic_store_unordered(&mut dst, new_value);
+ atomic_store_unordered(&mut dst, new_value);
}
}
diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-5.rs b/gcc/testsuite/rust/compile/torture/intrinsics-5.rs
index 7fd84dc..ffad0bd 100644
--- a/gcc/testsuite/rust/compile/torture/intrinsics-5.rs
+++ b/gcc/testsuite/rust/compile/torture/intrinsics-5.rs
@@ -1,4 +1,61 @@
-trait Copy {}
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+ fn clone(&self) -> Self;
+
+ fn clone_from(&mut self, source: &Self) {
+ *self = source.clone()
+ }
+}
+
+mod impls {
+ use super::Clone;
+
+ macro_rules! impl_clone {
+ ($($t:ty)*) => {
+ $(
+ impl Clone for $t {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+ )*
+ }
+ }
+
+ impl_clone! {
+ usize u8 u16 u32 u64 // u128
+ isize i8 i16 i32 i64 // i128
+ f32 f64
+ bool char
+ }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+ // Empty.
+}
+
+mod copy_impls {
+ use super::Copy;
+
+ macro_rules! impl_copy {
+ ($($t:ty)*) => {
+ $(
+ impl Copy for $t {}
+ )*
+ }
+ }
+
+ impl_copy! {
+ usize u8 u16 u32 u64 // u128
+ isize i8 i16 i32 i64 // i128
+ f32 f64
+ bool char
+ }
+}
extern "rust-intrinsic" {
pub fn atomic_store_seqcst<T: Copy>(dst: *mut T, value: T);
@@ -24,6 +81,13 @@ impl VeryLargeType {
}
}
+impl Clone for VeryLargeType {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+impl Copy for VeryLargeType {}
+
fn main() {
let mut dst = VeryLargeType::new(0);
let mut b = false;
diff --git a/gcc/testsuite/rust/execute/torture/atomic_load.rs b/gcc/testsuite/rust/execute/torture/atomic_load.rs
index 28ed8ae..6e7383a 100644
--- a/gcc/testsuite/rust/execute/torture/atomic_load.rs
+++ b/gcc/testsuite/rust/execute/torture/atomic_load.rs
@@ -1,4 +1,61 @@
-trait Copy {}
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+ fn clone(&self) -> Self;
+
+ fn clone_from(&mut self, source: &Self) {
+ *self = source.clone()
+ }
+}
+
+mod impls {
+ use super::Clone;
+
+ macro_rules! impl_clone {
+ ($($t:ty)*) => {
+ $(
+ impl Clone for $t {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+ )*
+ }
+ }
+
+ impl_clone! {
+ usize u8 u16 u32 u64 // u128
+ isize i8 i16 i32 i64 // i128
+ f32 f64
+ bool char
+ }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+ // Empty.
+}
+
+mod copy_impls {
+ use super::Copy;
+
+ macro_rules! impl_copy {
+ ($($t:ty)*) => {
+ $(
+ impl Copy for $t {}
+ )*
+ }
+ }
+
+ impl_copy! {
+ usize u8 u16 u32 u64 // u128
+ isize i8 i16 i32 i64 // i128
+ f32 f64
+ bool char
+ }
+}
extern "rust-intrinsic" {
pub fn atomic_load_seqcst<T: Copy>(src: *const T) -> T;
diff --git a/gcc/testsuite/rust/execute/torture/atomic_store.rs b/gcc/testsuite/rust/execute/torture/atomic_store.rs
index 9f248b4..46960a7 100644
--- a/gcc/testsuite/rust/execute/torture/atomic_store.rs
+++ b/gcc/testsuite/rust/execute/torture/atomic_store.rs
@@ -1,4 +1,61 @@
-trait Copy {}
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+ fn clone(&self) -> Self;
+
+ fn clone_from(&mut self, source: &Self) {
+ *self = source.clone()
+ }
+}
+
+mod impls {
+ use super::Clone;
+
+ macro_rules! impl_clone {
+ ($($t:ty)*) => {
+ $(
+ impl Clone for $t {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+ )*
+ }
+ }
+
+ impl_clone! {
+ usize u8 u16 u32 u64 // u128
+ isize i8 i16 i32 i64 // i128
+ f32 f64
+ bool char
+ }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+ // Empty.
+}
+
+mod copy_impls {
+ use super::Copy;
+
+ macro_rules! impl_copy {
+ ($($t:ty)*) => {
+ $(
+ impl Copy for $t {}
+ )*
+ }
+ }
+
+ impl_copy! {
+ usize u8 u16 u32 u64 // u128
+ isize i8 i16 i32 i64 // i128
+ f32 f64
+ bool char
+ }
+}
extern "rust-intrinsic" {
pub fn atomic_store_seqcst<T: Copy>(dst: *mut T, val: T);
diff --git a/gcc/testsuite/rust/execute/torture/issue-1720-2.rs b/gcc/testsuite/rust/execute/torture/issue-1720-2.rs
new file mode 100644
index 0000000..35833db
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1720-2.rs
@@ -0,0 +1,30 @@
+mod core {
+ mod ops {
+ #[lang = "add"]
+ pub trait Add<Rhs = Self> {
+ type Output;
+
+ fn add(self, rhs: Rhs) -> Self::Output;
+ }
+ }
+}
+
+struct Foo(i32);
+
+impl core::ops::Add for Foo {
+ type Output = i32;
+
+ fn add(self, rhs: Foo) -> Self::Output {
+ self.0 + rhs.0
+ }
+}
+
+pub fn bar<T: core::ops::Add<Output = i32>>(a: T) -> i32 {
+ a + a
+}
+
+pub fn main() -> i32 {
+ let a = Foo(1);
+
+ bar(a) - 2
+}