diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-08-17 17:28:15 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-08-19 15:39:21 +0100 |
commit | 1dc718474044149ec1aa6bee9ea8e83d778f17f2 (patch) | |
tree | 688bcd5d3a550681afaa87b90c848f365d425bcb /gcc | |
parent | c25cdc84600e81bfd4d1ae104ff9eb524f7c49f0 (diff) | |
download | gcc-1dc718474044149ec1aa6bee9ea8e83d778f17f2.zip gcc-1dc718474044149ec1aa6bee9ea8e83d778f17f2.tar.gz gcc-1dc718474044149ec1aa6bee9ea8e83d778f17f2.tar.bz2 |
optional trait item with associated types
Diffstat (limited to 'gcc')
20 files changed, 756 insertions, 90 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 0d0ca1d..7ed380e 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -80,6 +80,7 @@ GRS_OBJS = \ rust/rust-tyty.o \ rust/rust-tyctx.o \ rust/rust-tyty-bounds.o \ + rust/rust-hir-type-check-util.o \ rust/rust-hir-trait-resolve.o \ rust/rust-hir-const-fold.o \ rust/rust-lint-marklive.o \ diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 8a3d413..6356ccc 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -336,10 +336,13 @@ public: void visit (TyTy::InferType &) override { gcc_unreachable (); } - void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); } - void visit (TyTy::ProjectionType &) override { gcc_unreachable (); } + void visit (TyTy::PlaceholderType &type) override + { + type.resolve ()->accept_vis (*this); + } + void visit (TyTy::ParamType ¶m) override { param.resolve ()->accept_vis (*this); diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h index e446cf9..809cf56 100644 --- a/gcc/rust/backend/rust-compile-implitem.h +++ b/gcc/rust/backend/rust-compile-implitem.h @@ -319,15 +319,17 @@ public: // items can be forward compiled which means we may not need to invoke this // code. We might also have already compiled this generic function as well. Bfunction *lookup = nullptr; - if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup, fntype)) + if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup)) { // has this been added to the list then it must be finished if (ctx->function_completed (lookup)) { Bfunction *dummy = nullptr; if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy)) - ctx->insert_function_decl (fntype->get_ty_ref (), lookup, fntype); - + { + ctx->insert_function_decl (fntype->get_ty_ref (), lookup, + fntype); + } return; } } diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index 97ba15d..1b892d2 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -76,6 +76,7 @@ ResolvePathRef::visit (HIR::PathInExpression &expr) &lookup); rust_assert (ok); rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF); + TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup); Bfunction *fn = nullptr; if (!ctx->lookup_function_decl (lookup->get_ty_ref (), &fn)) @@ -145,28 +146,32 @@ ResolvePathRef::visit (HIR::PathInExpression &expr) rust_assert ( trait_item_ref->is_optional ()); // has definition - // FIXME - // TyTy::BaseType *self_type = nullptr; - // if (!ctx->get_tyctx ()->lookup_type ( - // expr.get_receiver ()->get_mappings ().get_hirid (), - // &self_type)) - // { - // rust_error_at (expr.get_locus (), - // "failed to resolve type for self param"); - // return; - // } - - // CompileTraitItem::Compile ( - // self_type, trait_item_ref->get_hir_trait_item (), ctx, - // fntype); - // if (!ctx->lookup_function_decl (fntype->get_ty_ref (), - // &fn)) - // { - // translated = ctx->get_backend ()->error_expression (); - // rust_error_at (expr.get_locus (), - // "forward declaration was not compiled"); - // return; - // } + Analysis::NodeMapping trait_mappings + = trait_item_ref->get_parent_trait_mappings (); + auto associated_impl_id + = ctx->get_tyctx () + ->lookup_associated_impl_mapping_for_self ( + trait_mappings.get_hirid (), receiver); + rust_assert (associated_impl_id != UNKNOWN_HIRID); + + Resolver::AssociatedImplTrait *associated = nullptr; + bool found_associated_trait_impl + = ctx->get_tyctx ()->lookup_associated_trait_impl ( + associated_impl_id, &associated); + rust_assert (found_associated_trait_impl); + associated->setup_associated_types (); + + CompileTraitItem::Compile ( + receiver, trait_item_ref->get_hir_trait_item (), ctx, + fntype); + + if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &fn)) + { + resolved = ctx->get_backend ()->error_expression (); + rust_error_at (expr.get_locus (), + "forward declaration was not compiled"); + return; + } } else { diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h index 22b1074..f737141 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.h +++ b/gcc/rust/typecheck/rust-hir-path-probe.h @@ -51,6 +51,7 @@ struct PathProbeCandidate { const TraitReference *trait_ref; const TraitItemReference *item_ref; + HIR::ImplBlock *impl; }; CandidateType type; @@ -128,19 +129,22 @@ public: if (!probe_bounds) return probe.candidates; - std::vector<TraitReference *> probed_bounds + std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> probed_bounds = TypeBoundsProbe::Probe (receiver); - std::vector<const TraitReference *> specified_bounds; + std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> + specified_bounds; for (const TyTy::TypeBoundPredicate &predicate : receiver->get_specified_bounds ()) { const TraitReference *trait_item = predicate.get (); - specified_bounds.push_back (trait_item); + + // FIXME lookup impl_block for this trait impl for this receiver + specified_bounds.push_back ({trait_item, nullptr}); } - std::vector<const TraitReference *> union_type_bounds - = probe.union_bounds (probed_bounds, specified_bounds); + std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> + union_type_bounds = probe.union_bounds (probed_bounds, specified_bounds); probe.process_traits_for_candidates (union_type_bounds, ignore_mandatory_trait_items); return probe.candidates; @@ -230,11 +234,15 @@ private: } void process_traits_for_candidates ( - const std::vector<const TraitReference *> traits, + const std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> + traits, bool ignore_mandatory_trait_items) { - for (const TraitReference *trait_ref : traits) + for (auto &ref : traits) { + const TraitReference *trait_ref = ref.first; + HIR::ImplBlock *impl = ref.second; + const TraitItemReference *trait_item_ref = nullptr; if (!trait_ref->lookup_trait_item (search.as_string (), &trait_item_ref)) @@ -296,7 +304,7 @@ private: } PathProbeCandidate::TraitItemCandidate trait_item_candidate{ - trait_ref, trait_item_ref}; + trait_ref, trait_item_ref, impl}; PathProbeCandidate candidate{candidate_type, trait_item_tyty, trait_ref->get_locus (), @@ -312,24 +320,27 @@ private: current_impl (nullptr) {} - std::vector<const TraitReference *> - union_bounds (const std::vector</*const*/ TraitReference *> a, - const std::vector<const TraitReference *> b) const + 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, const TraitReference *> mapper; - for (const TraitReference *ref : a) + std::map<DefId, std::pair<const TraitReference *, HIR::ImplBlock *>> mapper; + for (auto &ref : a) { - mapper.insert ({ref->get_mappings ().get_defid (), ref}); + mapper.insert ({ref.first->get_mappings ().get_defid (), ref}); } - for (const TraitReference *ref : b) + for (auto &ref : b) { - mapper.insert ({ref->get_mappings ().get_defid (), ref}); + mapper.insert ({ref.first->get_mappings ().get_defid (), ref}); } - std::vector<const TraitReference *> union_set; + 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); + union_set.push_back ({it->second.first, it->second.second}); } return union_set; } diff --git a/gcc/rust/typecheck/rust-hir-trait-ref.h b/gcc/rust/typecheck/rust-hir-trait-ref.h index 718b3ce..2c7a0e8 100644 --- a/gcc/rust/typecheck/rust-hir-trait-ref.h +++ b/gcc/rust/typecheck/rust-hir-trait-ref.h @@ -21,6 +21,7 @@ #include "rust-hir-full.h" #include "rust-tyty-visitor.h" +#include "rust-hir-type-check-util.h" namespace Rust { namespace Resolver { @@ -148,6 +149,8 @@ public: return get_error (); } + Analysis::NodeMapping get_parent_trait_mappings () const; + // this is called when the trait is completed resolution and gives the items a // chance to run their specific type resolution passes. If we call their // resolution on construction it can lead to a case where the trait being @@ -155,6 +158,10 @@ public: // the trait will not be stored in its own map yet void on_resolved (); + void associated_type_set (TyTy::BaseType *ty); + + void associated_type_reset (); + private: TyTy::ErrorType *get_error () const { @@ -186,6 +193,7 @@ private: Resolver::TypeCheckContext *context; }; +// this wraps up the HIR::Trait so we can do analysis on it class TraitReference { public: @@ -316,11 +324,48 @@ public: } } + void clear_associated_types () + { + for (auto &item : item_refs) + { + bool is_assoc_type = item.get_trait_item_type () + == TraitItemReference::TraitItemType::TYPE; + if (is_assoc_type) + item.associated_type_reset (); + } + } + private: const HIR::Trait *hir_trait_ref; std::vector<TraitItemReference> item_refs; }; +class AssociatedImplTrait +{ +public: + AssociatedImplTrait (TraitReference *trait, HIR::ImplBlock *impl, + TyTy::BaseType *self, + Resolver::TypeCheckContext *context) + : trait (trait), impl (impl), self (self), context (context) + {} + + TraitReference *get_trait () { return trait; } + + HIR::ImplBlock *get_impl_block () { return impl; } + + TyTy::BaseType *get_self () { return self; } + + void setup_associated_types (); + + void reset_associated_types (); + +private: + TraitReference *trait; + HIR::ImplBlock *impl; + TyTy::BaseType *self; + Resolver::TypeCheckContext *context; +}; + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc index d760709..5d7c71e 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc @@ -25,10 +25,6 @@ namespace Resolver { void ResolveTraitItemToRef::visit (HIR::TraitItemType &type) { - TyTy::BaseType *ty - = new TyTy::PlaceholderType (type.get_mappings ().get_hirid ()); - context->insert_type (type.get_mappings (), ty); - // create trait-item-ref Location locus = type.get_locus (); bool is_optional = false; @@ -92,7 +88,10 @@ TraitItemReference::on_resolved () void TraitItemReference::resolve_item (HIR::TraitItemType &type) { - // TODO + TyTy::BaseType *ty + = new TyTy::PlaceholderType (type.get_name (), + type.get_mappings ().get_hirid ()); + context->insert_type (type.get_mappings (), ty); } void @@ -128,5 +127,71 @@ TraitItemReference::resolve_item (HIR::TraitItemFunc &func) expected_ret_tyty->unify (block_expr_ty); } +void +TraitItemReference::associated_type_set (TyTy::BaseType *ty) +{ + rust_assert (get_trait_item_type () == TraitItemType::TYPE); + + TyTy::BaseType *item_ty = get_tyty (); + rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER); + TyTy::PlaceholderType *placeholder + = static_cast<TyTy::PlaceholderType *> (item_ty); + + placeholder->set_associated_type (ty->get_ref ()); +} + +void +TraitItemReference::associated_type_reset () +{ + rust_assert (get_trait_item_type () == TraitItemType::TYPE); + + TyTy::BaseType *item_ty = get_tyty (); + rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER); + TyTy::PlaceholderType *placeholder + = static_cast<TyTy::PlaceholderType *> (item_ty); + + placeholder->clear_associated_type (); +} + +void +AssociatedImplTrait::setup_associated_types () +{ + ImplTypeIterator iter (*impl, [&] (HIR::TypeAlias &type) { + TraitItemReference *resolved_trait_item = nullptr; + bool ok = trait->lookup_trait_item (type.get_new_type_name (), + &resolved_trait_item); + if (!ok) + return; + if (resolved_trait_item->get_trait_item_type () + != TraitItemReference::TraitItemType::TYPE) + return; + + TyTy::BaseType *lookup; + if (!context->lookup_type (type.get_mappings ().get_hirid (), &lookup)) + return; + + resolved_trait_item->associated_type_set (lookup); + }); + iter.go (); +} + +void +AssociatedImplTrait::reset_associated_types () +{ + trait->clear_associated_types (); +} + +Analysis::NodeMapping +TraitItemReference::get_parent_trait_mappings () const +{ + auto mappings = Analysis::Mappings::get (); + + HIR::Trait *trait + = mappings->lookup_trait_item_mapping (get_mappings ().get_hirid ()); + rust_assert (trait != nullptr); + + return trait->get_mappings (); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-bounds.h b/gcc/rust/typecheck/rust-hir-type-bounds.h index 2c06134..1ba6049 100644 --- a/gcc/rust/typecheck/rust-hir-type-bounds.h +++ b/gcc/rust/typecheck/rust-hir-type-bounds.h @@ -31,7 +31,8 @@ class TypeBoundsProbe : public TypeCheckBase using Rust::Resolver::TypeCheckBase::visit; public: - static std::vector<TraitReference *> Probe (const TyTy::BaseType *receiver) + static std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> + Probe (const TyTy::BaseType *receiver) { TypeBoundsProbe probe (receiver); probe.scan (); @@ -41,9 +42,11 @@ public: static bool is_bound_satisfied_for_type (TyTy::BaseType *receiver, TraitReference *ref) { - std::vector<TraitReference *> bounds = Probe (receiver); - for (TraitReference *b : bounds) + std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> bounds + = Probe (receiver); + for (auto &bound : bounds) { + TraitReference *b = bound.first; if (b == ref) return true; } @@ -59,7 +62,7 @@ private: {} const TyTy::BaseType *receiver; - std::vector<TraitReference *> trait_references; + std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> trait_references; }; } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index d82b5c7..0ac60c2 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -975,7 +975,6 @@ public: } // TODO self and generic arguments - infered = trait_item_ref->get_tyty (); rust_debug_loc (expr.get_locus (), "resolved to:"); infered->debug (); @@ -1370,6 +1369,22 @@ private: { resolved_node_id = candidate.item.trait.item_ref->get_mappings ().get_nodeid (); + + // lookup the associated-impl-trait + HIR::ImplBlock *impl = candidate.item.trait.impl; + if (impl != nullptr) + { + AssociatedImplTrait *lookup_associated = nullptr; + bool found_impl_trait = context->lookup_associated_trait_impl ( + impl->get_mappings ().get_hirid (), &lookup_associated); + rust_assert (found_impl_trait); + + lookup_associated->setup_associated_types (); + + // we need a new ty_ref_id for this trait item + tyseg = tyseg->clone (); + tyseg->set_ty_ref (mappings->get_next_hir_id ()); + } } if (seg.has_generic_args ()) diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index 65088be..3d83523 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -383,8 +383,7 @@ public: trait_reference.get_name ().c_str ()); } - context->insert_type (resolved_trait_item.get_mappings (), - lookup->clone ()); + resolved_trait_item.associated_type_set (lookup); } void visit (HIR::Function &function) override diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index 372171f..72da26d 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -123,6 +123,19 @@ public: trait_reference->get_name ().c_str ()); } } + + if (is_trait_impl_block) + { + trait_reference->clear_associated_types (); + + AssociatedImplTrait associated (trait_reference, &impl_block, self, + context); + context->insert_associated_trait_impl ( + impl_block.get_mappings ().get_hirid (), std::move (associated)); + context->insert_associated_impl_mapping ( + trait_reference->get_mappings ().get_hirid (), self, + impl_block.get_mappings ().get_hirid ()); + } } void visit (HIR::Function &function) override diff --git a/gcc/rust/typecheck/rust-hir-type-check-util.cc b/gcc/rust/typecheck/rust-hir-type-check-util.cc new file mode 100644 index 0000000..82bd081 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-util.cc @@ -0,0 +1,41 @@ +// Copyright (C) 2021 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-util.h" +#include "rust-hir-full.h" + +namespace Rust { +namespace Resolver { + +void +ImplTypeIterator::go () +{ + for (auto &item : impl.get_impl_items ()) + { + item->accept_vis (*this); + } +} + +void +ImplTypeIterator::visit (HIR::TypeAlias &alias) +{ + cb (alias); +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-util.h b/gcc/rust/typecheck/rust-hir-type-check-util.h new file mode 100644 index 0000000..0ba07a1 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-util.h @@ -0,0 +1,216 @@ +// Copyright (C) 2021 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_HIR_TYPE_CHECK_UTIL_H +#define RUST_HIR_TYPE_CHECK_UTIL_H + +#include <functional> +#include "rust-hir-visitor.h" + +namespace Rust { +namespace Resolver { + +class SimpleHirVisitor : public HIR::HIRVisitor +{ +public: + virtual ~SimpleHirVisitor () {} + + virtual void visit (HIR::IdentifierExpr &) override {} + virtual void visit (HIR::Lifetime &) override {} + virtual void visit (HIR::LifetimeParam &) override {} + virtual void visit (HIR::PathInExpression &) override {} + virtual void visit (HIR::TypePathSegment &) override {} + virtual void visit (HIR::TypePathSegmentGeneric &) override {} + virtual void visit (HIR::TypePathSegmentFunction &) override {} + virtual void visit (HIR::TypePath &) override {} + virtual void visit (HIR::QualifiedPathInExpression &) override {} + virtual void visit (HIR::QualifiedPathInType &) override {} + + virtual void visit (HIR::LiteralExpr &) override {} + virtual void visit (HIR::BorrowExpr &) override {} + virtual void visit (HIR::DereferenceExpr &) override {} + virtual void visit (HIR::ErrorPropagationExpr &) override {} + virtual void visit (HIR::NegationExpr &) override {} + virtual void visit (HIR::ArithmeticOrLogicalExpr &) override {} + virtual void visit (HIR::ComparisonExpr &) override {} + virtual void visit (HIR::LazyBooleanExpr &) override {} + virtual void visit (HIR::TypeCastExpr &) override {} + virtual void visit (HIR::AssignmentExpr &) override {} + + virtual void visit (HIR::GroupedExpr &) override {} + + virtual void visit (HIR::ArrayElemsValues &) override {} + virtual void visit (HIR::ArrayElemsCopied &) override {} + virtual void visit (HIR::ArrayExpr &) override {} + virtual void visit (HIR::ArrayIndexExpr &) override {} + virtual void visit (HIR::TupleExpr &) override {} + virtual void visit (HIR::TupleIndexExpr &) override {} + virtual void visit (HIR::StructExprStruct &) override {} + + virtual void visit (HIR::StructExprFieldIdentifier &) override {} + virtual void visit (HIR::StructExprFieldIdentifierValue &) override {} + + virtual void visit (HIR::StructExprFieldIndexValue &) override {} + virtual void visit (HIR::StructExprStructFields &) override {} + virtual void visit (HIR::StructExprStructBase &) override {} + virtual void visit (HIR::StructExprTuple &) override {} + virtual void visit (HIR::StructExprUnit &) override {} + + virtual void visit (HIR::EnumExprFieldIdentifier &) override {} + virtual void visit (HIR::EnumExprFieldIdentifierValue &) override {} + + virtual void visit (HIR::EnumExprFieldIndexValue &) override {} + virtual void visit (HIR::EnumExprStruct &) override {} + virtual void visit (HIR::EnumExprTuple &) override {} + virtual void visit (HIR::EnumExprFieldless &) override {} + virtual void visit (HIR::CallExpr &) override {} + virtual void visit (HIR::MethodCallExpr &) override {} + virtual void visit (HIR::FieldAccessExpr &) override {} + virtual void visit (HIR::ClosureExprInner &) override {} + virtual void visit (HIR::BlockExpr &) override {} + virtual void visit (HIR::ClosureExprInnerTyped &) override {} + virtual void visit (HIR::ContinueExpr &) override {} + virtual void visit (HIR::BreakExpr &) override {} + virtual void visit (HIR::RangeFromToExpr &) override {} + virtual void visit (HIR::RangeFromExpr &) override {} + virtual void visit (HIR::RangeToExpr &) override {} + virtual void visit (HIR::RangeFullExpr &) override {} + virtual void visit (HIR::RangeFromToInclExpr &) override {} + virtual void visit (HIR::RangeToInclExpr &) override {} + virtual void visit (HIR::ReturnExpr &) override {} + virtual void visit (HIR::UnsafeBlockExpr &) override {} + virtual void visit (HIR::LoopExpr &) override {} + virtual void visit (HIR::WhileLoopExpr &) override {} + virtual void visit (HIR::WhileLetLoopExpr &) override {} + virtual void visit (HIR::ForLoopExpr &) override {} + virtual void visit (HIR::IfExpr &) override {} + virtual void visit (HIR::IfExprConseqElse &) override {} + virtual void visit (HIR::IfExprConseqIf &) override {} + virtual void visit (HIR::IfExprConseqIfLet &) override {} + virtual void visit (HIR::IfLetExpr &) override {} + virtual void visit (HIR::IfLetExprConseqElse &) override {} + virtual void visit (HIR::IfLetExprConseqIf &) override {} + virtual void visit (HIR::IfLetExprConseqIfLet &) override {} + + virtual void visit (HIR::MatchExpr &) override {} + virtual void visit (HIR::AwaitExpr &) override {} + virtual void visit (HIR::AsyncBlockExpr &) override {} + + virtual void visit (HIR::TypeParam &) override {} + + virtual void visit (HIR::LifetimeWhereClauseItem &) override {} + virtual void visit (HIR::TypeBoundWhereClauseItem &) override {} + virtual void visit (HIR::ModuleBodied &) override {} + virtual void visit (HIR::ModuleNoBody &) override {} + virtual void visit (HIR::ExternCrate &) override {} + + virtual void visit (HIR::UseTreeGlob &) override {} + virtual void visit (HIR::UseTreeList &) override {} + virtual void visit (HIR::UseTreeRebind &) override {} + virtual void visit (HIR::UseDeclaration &) override {} + virtual void visit (HIR::Function &) override {} + virtual void visit (HIR::TypeAlias &) override {} + virtual void visit (HIR::StructStruct &) override {} + virtual void visit (HIR::TupleStruct &) override {} + virtual void visit (HIR::EnumItem &) override {} + virtual void visit (HIR::EnumItemTuple &) override {} + virtual void visit (HIR::EnumItemStruct &) override {} + virtual void visit (HIR::EnumItemDiscriminant &) override {} + virtual void visit (HIR::Enum &) override {} + virtual void visit (HIR::Union &) override {} + virtual void visit (HIR::ConstantItem &) override {} + virtual void visit (HIR::StaticItem &) override {} + virtual void visit (HIR::TraitItemFunc &) override {} + virtual void visit (HIR::TraitItemConst &) override {} + virtual void visit (HIR::TraitItemType &) override {} + virtual void visit (HIR::Trait &) override {} + virtual void visit (HIR::ImplBlock &) override {} + + virtual void visit (HIR::ExternalStaticItem &) override {} + virtual void visit (HIR::ExternalFunctionItem &) override {} + virtual void visit (HIR::ExternBlock &) override {} + + virtual void visit (HIR::LiteralPattern &) override {} + virtual void visit (HIR::IdentifierPattern &) override {} + virtual void visit (HIR::WildcardPattern &) override {} + + virtual void visit (HIR::RangePatternBoundLiteral &) override {} + virtual void visit (HIR::RangePatternBoundPath &) override {} + virtual void visit (HIR::RangePatternBoundQualPath &) override {} + virtual void visit (HIR::RangePattern &) override {} + virtual void visit (HIR::ReferencePattern &) override {} + + virtual void visit (HIR::StructPatternFieldTuplePat &) override {} + virtual void visit (HIR::StructPatternFieldIdentPat &) override {} + virtual void visit (HIR::StructPatternFieldIdent &) override {} + virtual void visit (HIR::StructPattern &) override {} + + virtual void visit (HIR::TupleStructItemsNoRange &) override {} + virtual void visit (HIR::TupleStructItemsRange &) override {} + virtual void visit (HIR::TupleStructPattern &) override {} + + virtual void visit (HIR::TuplePatternItemsMultiple &) override {} + virtual void visit (HIR::TuplePatternItemsRanged &) override {} + virtual void visit (HIR::TuplePattern &) override {} + virtual void visit (HIR::GroupedPattern &) override {} + virtual void visit (HIR::SlicePattern &) override {} + + virtual void visit (HIR::EmptyStmt &) override {} + virtual void visit (HIR::LetStmt &) override {} + virtual void visit (HIR::ExprStmtWithoutBlock &) override {} + virtual void visit (HIR::ExprStmtWithBlock &) override {} + + virtual void visit (HIR::TraitBound &) override {} + virtual void visit (HIR::ImplTraitType &) override {} + virtual void visit (HIR::TraitObjectType &) override {} + virtual void visit (HIR::ParenthesisedType &) override {} + virtual void visit (HIR::ImplTraitTypeOneBound &) override {} + virtual void visit (HIR::TraitObjectTypeOneBound &) override {} + virtual void visit (HIR::TupleType &) override {} + virtual void visit (HIR::NeverType &) override {} + virtual void visit (HIR::RawPointerType &) override {} + virtual void visit (HIR::ReferenceType &) override {} + virtual void visit (HIR::ArrayType &) override {} + virtual void visit (HIR::SliceType &) override {} + virtual void visit (HIR::InferredType &) override {} + virtual void visit (HIR::BareFunctionType &) override {} +}; + +class ImplTypeIterator : public SimpleHirVisitor +{ + using SimpleHirVisitor::visit; + +public: + ImplTypeIterator (HIR::ImplBlock &impl, + std::function<void (HIR::TypeAlias &alias)> cb) + : impl (impl), cb (cb) + {} + + void go (); + + void visit (HIR::TypeAlias &alias) override; + +private: + HIR::ImplBlock &impl; + std::function<void (HIR::TypeAlias &alias)> cb; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_UTIL_H diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index d834ad8..27b7f12 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -117,6 +117,70 @@ public: return true; } + 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)); + } + + 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) + { + associated_type_mappings[id] = UNKNOWN_HIRID; + } + + HirId lookup_associated_type_mapping (HirId id, HirId default_value) + { + auto it = associated_type_mappings.find (id); + if (it == associated_type_mappings.end ()) + return default_value; + + return it->second; + } + + 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 lookup_associated_impl_mapping_for_self (HirId trait_id, + const TyTy::BaseType *self) + { + auto it = associated_traits_to_impls.find (trait_id); + if (it == associated_traits_to_impls.end ()) + return UNKNOWN_HIRID; + + for (auto &item : it->second) + { + if (item.first->can_eq (self, false)) + return item.second; + } + return UNKNOWN_HIRID; + } + private: TypeCheckContext (); @@ -127,6 +191,13 @@ private: std::vector<TyTy::BaseType *> loop_type_stack; std::map<DefId, TraitReference> trait_context; std::map<HirId, TyTy::BaseType *> receiver_context; + std::map<HirId, AssociatedImplTrait> associated_impl_traits; + + // trait-id -> list of < self-tyty:impl-id> + std::map<HirId, std::vector<std::pair<const TyTy::BaseType *, HirId>>> + associated_traits_to_impls; + + std::map<HirId, HirId> associated_type_mappings; }; class TypeResolution diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index 008dc19..1bd7865 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -25,7 +25,8 @@ namespace Resolver { void TypeBoundsProbe::scan () { - std::vector<HIR::TypePath *> possible_trait_paths; + std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>> + possible_trait_paths; mappings->iterate_impl_blocks ( [&] (HirId id, HIR::ImplBlock *impl) mutable -> bool { // we are filtering for trait-impl-blocks @@ -42,16 +43,17 @@ TypeBoundsProbe::scan () if (!receiver->can_eq (impl_type, false)) return true; - possible_trait_paths.push_back (impl->get_trait_ref ().get ()); + possible_trait_paths.push_back ({impl->get_trait_ref ().get (), impl}); return true; }); - for (auto &trait_path : possible_trait_paths) + for (auto &path : possible_trait_paths) { + HIR::TypePath *trait_path = path.first; TraitReference *trait_ref = TraitResolver::Resolve (*trait_path); if (!trait_ref->is_error ()) - trait_references.push_back (trait_ref); + trait_references.push_back ({trait_ref, path.second}); } } diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h index 6801084..100e384 100644 --- a/gcc/rust/typecheck/rust-tyty-cmp.h +++ b/gcc/rust/typecheck/rust-tyty-cmp.h @@ -43,6 +43,16 @@ public: return ok; } } + else if (other->get_kind () == TypeKind::PLACEHOLDER) + { + const PlaceholderType *p = static_cast<const PlaceholderType *> (other); + if (p->can_resolve ()) + { + const BaseType *resolved = p->resolve (); + resolved->accept_vis (*this); + return ok; + } + } other->accept_vis (*this); return ok; @@ -1165,43 +1175,55 @@ public: : BaseCmp (base, emit_errors), base (base) {} - virtual void visit (const TupleType &) override { ok = true; } + bool can_eq (const BaseType *other) override + { + if (!base->can_resolve ()) + return BaseCmp::can_eq (other); + + BaseType *lookup = base->resolve (); + return lookup->can_eq (other, emit_error_flag); + } + + void visit (const TupleType &) override { ok = true; } - virtual void visit (const ADTType &) override { ok = true; } + void visit (const ADTType &) override { ok = true; } - virtual void visit (const InferType &) override { ok = true; } + void visit (const InferType &) override { ok = true; } - virtual void visit (const FnType &) override { ok = true; } + void visit (const FnType &) override { ok = true; } - virtual void visit (const FnPtr &) override { ok = true; } + void visit (const FnPtr &) override { ok = true; } - virtual void visit (const ArrayType &) override { ok = true; } + void visit (const ArrayType &) override { ok = true; } - virtual void visit (const BoolType &) override { ok = true; } + void visit (const BoolType &) override { ok = true; } - virtual void visit (const IntType &) override { ok = true; } + void visit (const IntType &) override { ok = true; } - virtual void visit (const UintType &) override { ok = true; } + void visit (const UintType &) override { ok = true; } - virtual void visit (const USizeType &) override { ok = true; } + void visit (const USizeType &) override { ok = true; } - virtual void visit (const ISizeType &) override { ok = true; } + void visit (const ISizeType &) override { ok = true; } - virtual void visit (const FloatType &) override { ok = true; } + void visit (const FloatType &) override { ok = true; } - virtual void visit (const ErrorType &) override { ok = true; } + void visit (const ErrorType &) override { ok = true; } - virtual void visit (const CharType &) override { ok = true; } + void visit (const CharType &) override { ok = true; } - virtual void visit (const ReferenceType &) override { ok = true; } + void visit (const ReferenceType &) override { ok = true; } - virtual void visit (const ParamType &) override { ok = true; } + void visit (const ParamType &) override { ok = true; } - virtual void visit (const StrType &) override { ok = true; } + void visit (const StrType &) override { ok = true; } - virtual void visit (const NeverType &) override { ok = true; } + void visit (const NeverType &) override { ok = true; } - virtual void visit (const PlaceholderType &) override { ok = true; } + void visit (const PlaceholderType &type) override + { + ok = base->get_symbol ().compare (type.get_symbol ()) == 0; + } private: const BaseType *get_base () const override { return base; } diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index ca4849b..4d0b977 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -68,6 +68,14 @@ public: other = p->resolve (); } } + else if (other->get_kind () == TypeKind::PLACEHOLDER) + { + PlaceholderType *p = static_cast<PlaceholderType *> (other); + if (p->can_resolve ()) + { + other = p->resolve (); + } + } other->accept_vis (*this); if (resolved->get_kind () == TyTy::TypeKind::ERROR) @@ -1249,7 +1257,7 @@ class NeverRules : public BaseRules public: NeverRules (NeverType *base) : BaseRules (base), base (base) {} - virtual void visit (NeverType &type) override { resolved = type.clone (); } + void visit (NeverType &type) override { resolved = type.clone (); } private: BaseType *get_base () override { return base; } @@ -1264,6 +1272,37 @@ class PlaceholderRules : public BaseRules 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; } diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index ca4b3b8..18ccaee 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -49,10 +49,10 @@ BaseType::satisfies_bound (const TypeBoundPredicate &predicate) const return true; } - std::vector<Resolver::TraitReference *> probed - = Resolver::TypeBoundsProbe::Probe (this); - for (const Resolver::TraitReference *bound : probed) + auto probed = Resolver::TypeBoundsProbe::Probe (this); + for (auto &b : probed) { + const Resolver::TraitReference *bound = b.first; bool found = bound->get_mappings ().get_defid () == query->get_mappings ().get_defid (); if (found) @@ -2032,7 +2032,8 @@ PlaceholderType::accept_vis (TyConstVisitor &vis) const std::string PlaceholderType::as_string () const { - return "<placeholder>"; + return "<placeholder:" + (can_resolve () ? resolve ()->as_string () : "") + + ">"; } BaseType * @@ -2066,7 +2067,59 @@ PlaceholderType::can_eq (const BaseType *other, bool emit_errors) const BaseType * PlaceholderType::clone () const { - return new PlaceholderType (get_ref (), get_ty_ref (), get_combined_refs ()); + return new PlaceholderType (get_symbol (), get_ref (), get_ty_ref (), + get_combined_refs ()); +} + +void +PlaceholderType::set_associated_type (HirId ref) +{ + auto context = Resolver::TypeCheckContext::get (); + context->insert_associated_type_mapping (get_ty_ref (), ref); +} + +void +PlaceholderType::clear_associated_type () +{ + auto context = Resolver::TypeCheckContext::get (); + context->clear_associated_type_mapping (get_ty_ref ()); +} + +bool +PlaceholderType::can_resolve () const +{ + auto context = Resolver::TypeCheckContext::get (); + HirId val + = context->lookup_associated_type_mapping (get_ty_ref (), UNKNOWN_HIRID); + return val != UNKNOWN_HIRID; +} + +BaseType * +PlaceholderType::resolve () const +{ + auto context = Resolver::TypeCheckContext::get (); + + rust_assert (can_resolve ()); + HirId val + = context->lookup_associated_type_mapping (get_ty_ref (), UNKNOWN_HIRID); + rust_assert (val != UNKNOWN_HIRID); + + return TyVar (val).get_tyty (); +} + +bool +PlaceholderType::is_equal (const BaseType &other) const +{ + if (get_kind () != other.get_kind ()) + { + if (!can_resolve ()) + return false; + + return resolve ()->is_equal (other); + } + + auto other2 = static_cast<const PlaceholderType &> (other); + return get_symbol ().compare (other2.get_symbol ()) == 0; } // Projection type @@ -2243,6 +2296,17 @@ TypeCheckCallExpr::visit (FnType &type) return; } + if (type.get_return_type ()->get_kind () == TyTy::TypeKind::PLACEHOLDER) + { + const TyTy::PlaceholderType *p + = static_cast<const TyTy::PlaceholderType *> (type.get_return_type ()); + if (p->can_resolve ()) + { + resolved = p->resolve ()->clone (); + return; + } + } + resolved = type.get_return_type ()->clone (); } diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index f01d6f8..2fc6b53 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -1683,13 +1683,15 @@ public: class PlaceholderType : public BaseType { public: - PlaceholderType (HirId ref, std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ref, TypeKind::PLACEHOLDER, refs) + PlaceholderType (std::string symbol, HirId ref, + std::set<HirId> refs = std::set<HirId> ()) + : BaseType (ref, ref, TypeKind::PLACEHOLDER, refs), symbol (symbol) + {} - PlaceholderType (HirId ref, HirId ty_ref, + PlaceholderType (std::string symbol, HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ty_ref, TypeKind::PLACEHOLDER, refs) + : BaseType (ref, ty_ref, TypeKind::PLACEHOLDER, refs), symbol (symbol) {} void accept_vis (TyVisitor &vis) override; @@ -1707,6 +1709,21 @@ public: std::string get_name () const override final { return as_string (); } bool is_unit () const override { return true; } + + std::string get_symbol () const { return symbol; } + + void set_associated_type (HirId ref); + + void clear_associated_type (); + + bool can_resolve () const; + + BaseType *resolve () const; + + bool is_equal (const BaseType &other) const override; + +private: + std::string symbol; }; class ProjectionType : public BaseType diff --git a/gcc/testsuite/rust/compile/torture/traits11.rs b/gcc/testsuite/rust/compile/torture/traits11.rs new file mode 100644 index 0000000..b5fc023 --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/traits11.rs @@ -0,0 +1,32 @@ +trait Foo { + type A; + // { dg-warning "unused name" "" { target *-*-* } .-1 } + + fn test(a: Self::A) -> Self::A { + a + } +} + +struct Bar(i32); +impl Foo for Bar { + type A = i32; +} + +struct Baz(f32); +impl Foo for Baz { + type A = f32; +} + +fn main() { + let a; + a = Bar(123); + + let b; + b = Bar::test(a.0); + + let c; + c = Baz(123f32); + + let d; + d = Baz::test(c.0); +} |