diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2023-02-05 00:56:44 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-05 00:56:44 +0000 |
commit | 8f1fce4916520b7ee9a97d2bb4f25d25fd94a626 (patch) | |
tree | fb2b8f475720233153b06864ffd4d5fc72ed35df /gcc | |
parent | 47a9a9e949d7660ae7fc7cd4642f668bf438c970 (diff) | |
parent | 6d7a7b22882433d46bf4e4efe8c43343892c91eb (diff) | |
download | gcc-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')
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 ¶m_mapping : fn->get_substs ()) + { + const HIR::TypeParam &type_param = param_mapping.get_generic_param (); + if (type_param.get_type_representation ().compare ("Self") == 0) + { + param = ¶m_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 ¶m_mapping : fn->get_substs ()) - { - const HIR::TypeParam &type_param - = param_mapping.get_generic_param (); - if (type_param.get_type_representation ().compare ("Self") == 0) - { - param = ¶m_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 ¶m = 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 (¶m, 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 ¶m_mapping = substitutions.at (i); + SubstitutionArg &arg = mappings.get_mappings ().at (i); + + if (param_mapping.needs_substitution ()) + { + SubstitutionArg adjusted (¶m_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 ¶m = 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 (¶m, 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 ¶m_mapping = substitutions.at (i); - SubstitutionArg &arg = mappings.get_mappings ().at (i); - - if (param_mapping.needs_substitution ()) - { - SubstitutionArg adjusted (¶m_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 ¶m, + 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 ¶m, + 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 ¶m, 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 ¶m, 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 ( + <ype->get_parameters ()), + TyTy::TyWithLocation (&type.get_parameters ()), + locus, commit_flag, false /* emit_error */); + if (args_res->get_kind () == TyTy::TypeKind::ERROR) + { + return new TyTy::ErrorType (0); + } + + TyTy::BaseType *res = UnifyRules::Resolve ( + TyTy::TyWithLocation (<ype->get_result_type ()), + TyTy::TyWithLocation (&type.get_result_type ()), locus, commit_flag, + false /* emit_error */); + if (res == nullptr || res->get_kind () == TyTy::TypeKind::ERROR) + { + return new TyTy::ErrorType (0); + } + + return ltype->clone (); + } + break; + + case TyTy::SLICE: + case TyTy::PARAM: + case TyTy::POINTER: + case TyTy::STR: + case TyTy::ADT: + case TyTy::REF: + case TyTy::ARRAY: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::UINT: + case TyTy::FLOAT: + case TyTy::USIZE: + case TyTy::ISIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +} // namespace Resolver +} // namespace Rust 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 +} |