diff options
Diffstat (limited to 'gcc')
30 files changed, 915 insertions, 170 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 9c69b44..64b9247 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -83,6 +83,7 @@ GRS_OBJS = \ rust/rust-hir-type-check-util.o \ rust/rust-hir-trait-resolve.o \ rust/rust-hir-const-fold.o \ + rust/rust-hir-type-check-type.o \ rust/rust-lint-marklive.o \ rust/rust-hir-type-check-path.o \ $(END) diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index dcfc3d1..0578329 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -3535,7 +3535,16 @@ public: void insert_implict_self (std::unique_ptr<AST::GenericParam> &¶m) { - generic_params.push_back (std::move (param)); + std::vector<std::unique_ptr<GenericParam>> new_list; + new_list.reserve (generic_params.size () + 1); + + new_list.push_back (std::move (param)); + for (auto &p : generic_params) + { + new_list.push_back (std::move (p)); + } + + generic_params = std::move (new_list); } protected: diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 6ccd3a0..8992993 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -1029,6 +1029,15 @@ public: } Location get_locus () const override final { return locus; } + + void iterate_segments (std::function<bool (TypePathSegment *)> cb) + { + for (auto it = segments.begin (); it != segments.end (); it++) + { + if (!cb ((*it).get ())) + return; + } + } }; } // namespace AST } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 66d037d..bffe97c 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -336,7 +336,10 @@ public: void visit (TyTy::InferType &) override { gcc_unreachable (); } - void visit (TyTy::ProjectionType &) override { gcc_unreachable (); } + void visit (TyTy::ProjectionType &type) override + { + type.get ()->accept_vis (*this); + } void visit (TyTy::PlaceholderType &type) override { diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index c16025d..464045a 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -28,6 +28,7 @@ namespace HIR { class ASTLowerTypePath : public ASTLoweringBase { +protected: using Rust::HIR::ASTLoweringBase::visit; public: @@ -88,9 +89,30 @@ public: mappings->insert_hir_type (crate_num, hirid, translated); } +protected: + HIR::TypePathSegment *translated_segment; + private: HIR::TypePath *translated; - HIR::TypePathSegment *translated_segment; +}; + +class ASTLowerQualifiedPathInType : public ASTLowerTypePath +{ + using ASTLowerTypePath::visit; + +public: + static HIR::QualifiedPathInType *translate (AST::QualifiedPathInType &type) + { + ASTLowerQualifiedPathInType resolver; + type.accept_vis (resolver); + rust_assert (resolver.translated != nullptr); + return resolver.translated; + } + + void visit (AST::QualifiedPathInType &path) override; + +private: + HIR::QualifiedPathInType *translated; }; class ASTLoweringType : public ASTLoweringBase @@ -187,6 +209,11 @@ public: translated = ASTLowerTypePath::translate (path); } + void visit (AST::QualifiedPathInType &path) override + { + translated = ASTLowerQualifiedPathInType::translate (path); + } + void visit (AST::ArrayType &type) override { HIR::Type *translated_type diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index d5138fd..e8784b6 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -450,6 +450,62 @@ ASTLowerTypePath::visit (AST::TypePathSegmentGeneric &segment) segment.get_locus ()); } +void +ASTLowerQualifiedPathInType::visit (AST::QualifiedPathInType &path) +{ + auto crate_num = mappings->get_current_crate (); + auto hirid = mappings->get_next_hir_id (crate_num); + Analysis::NodeMapping qual_mappings ( + crate_num, path.get_qualified_path_type ().get_node_id (), hirid, + UNKNOWN_LOCAL_DEFID); + + HIR::Type *qual_type = ASTLoweringType::translate ( + path.get_qualified_path_type ().get_type ().get ()); + HIR::TypePath *qual_trait = ASTLowerTypePath::translate ( + path.get_qualified_path_type ().get_as_type_path ()); + + HIR::QualifiedPathType qual_path_type ( + qual_mappings, std::unique_ptr<HIR::Type> (qual_type), + std::unique_ptr<HIR::TypePath> (qual_trait), + path.get_qualified_path_type ().get_locus ()); + + translated_segment = nullptr; + path.get_associated_segment ()->accept_vis (*this); + if (translated_segment == nullptr) + { + rust_fatal_error (path.get_associated_segment ()->get_locus (), + "failed to translate AST TypePathSegment"); + return; + } + std::unique_ptr<HIR::TypePathSegment> associated_segment (translated_segment); + + std::vector<std::unique_ptr<HIR::TypePathSegment> > translated_segments; + path.iterate_segments ([&] (AST::TypePathSegment *seg) mutable -> bool { + translated_segment = nullptr; + seg->accept_vis (*this); + if (translated_segment == nullptr) + { + rust_fatal_error (seg->get_locus (), + "failed to translate AST TypePathSegment"); + return false; + } + + translated_segments.push_back ( + std::unique_ptr<HIR::TypePathSegment> (translated_segment)); + return true; + }); + + Analysis::NodeMapping mapping (crate_num, path.get_node_id (), hirid, + mappings->get_next_localdef_id (crate_num)); + + translated = new HIR::QualifiedPathInType (std::move (mapping), + std::move (qual_path_type), + std::move (associated_segment), + std::move (translated_segments), + path.get_locus ()); + mappings->insert_hir_type (crate_num, hirid, translated); +} + // rust-ast-lower-base HIR::Type * diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h index 0e3c430..13e246f 100644 --- a/gcc/rust/hir/tree/rust-hir-path.h +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -767,6 +767,27 @@ public: rust_assert (has_as_clause ()); return trait; } + + bool trait_has_generic_args () const + { + rust_assert (has_as_clause ()); + bool is_generic_seg = trait->get_final_segment ()->get_type () + == TypePathSegment::SegmentType::GENERIC; + if (!is_generic_seg) + return false; + + TypePathSegmentGeneric *seg = static_cast<TypePathSegmentGeneric *> ( + trait->get_final_segment ().get ()); + return seg->has_generic_args (); + } + + GenericArgs &get_trait_generic_args () + { + rust_assert (trait_has_generic_args ()); + TypePathSegmentGeneric *seg = static_cast<TypePathSegmentGeneric *> ( + trait->get_final_segment ().get ()); + return seg->get_generic_args (); + } }; /* HIR node representing a qualified path-in-expression pattern (path that @@ -819,6 +840,7 @@ protected: class QualifiedPathInType : public TypeNoBounds { QualifiedPathType path_type; + std::unique_ptr<TypePathSegment> associated_segment; std::vector<std::unique_ptr<TypePathSegment> > segments; Location locus; @@ -840,9 +862,11 @@ protected: public: QualifiedPathInType ( Analysis::NodeMapping mappings, QualifiedPathType qual_path_type, + std::unique_ptr<TypePathSegment> associated_segment, std::vector<std::unique_ptr<TypePathSegment> > path_segments, Location locus = Location ()) : TypeNoBounds (mappings), path_type (std::move (qual_path_type)), + associated_segment (std::move (associated_segment)), segments (std::move (path_segments)), locus (locus) {} @@ -883,6 +907,20 @@ public: std::string as_string () const override; void accept_vis (HIRVisitor &vis) override; + + QualifiedPathType &get_path_type () { return path_type; } + + std::unique_ptr<TypePathSegment> &get_associated_segment () + { + return associated_segment; + } + + std::vector<std::unique_ptr<TypePathSegment> > &get_segments () + { + return segments; + } + + Location get_locus () { return locus; } }; } // namespace HIR } // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index 97c0311..9ad465a 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -97,6 +97,7 @@ public: class ResolveTypeToCanonicalPath : public ResolverBase { +protected: using Rust::Resolver::ResolverBase::visit; public: @@ -128,7 +129,7 @@ public: static bool type_resolve_generic_args (AST::GenericArgs &args); -private: +protected: ResolveTypeToCanonicalPath (bool include_generic_args, bool type_resolve_generic_args) : ResolverBase (UNKNOWN_NODEID), result (CanonicalPath::create_empty ()), @@ -182,8 +183,10 @@ public: } }; -class ResolveRelativeTypePath +class ResolveRelativeTypePath : public ResolveTypeToCanonicalPath { + using ResolveTypeToCanonicalPath::visit; + public: static NodeId go (AST::TypePath &path, NodeId parent, const CanonicalPath &prefix, @@ -218,6 +221,64 @@ public: return resolved_node; } + + static NodeId go (AST::QualifiedPathInType &path, NodeId parent, + const CanonicalPath &prefix, + bool canonicalize_type_with_generics) + { + auto &qualified_path = path.get_qualified_path_type (); + CanonicalPath result = prefix; + if (!resolve_qual_seg (qualified_path, result)) + return UNKNOWN_NODEID; + + // resolve the associated impl + auto resolver = Resolver::get (); + NodeId projection_resolved_id = UNKNOWN_NODEID; + if (!resolver->get_name_scope ().lookup (result, &projection_resolved_id)) + { + rust_error_at (path.get_locus (), + "failed to resolve associated path: %s", + result.get ().c_str ()); + + return UNKNOWN_NODEID; + } + // mark the resolution for this + resolver->insert_resolved_name (qualified_path.get_node_id (), + projection_resolved_id); + + // qualified types are similar to other paths in that we cannot guarantee + // that we can resolve the path at name resolution. We must look up + // associated types and type information to figure this out properly + + ResolveRelativeTypePath o (result); + std::unique_ptr<AST::TypePathSegment> &associated + = path.get_associated_segment (); + + associated->accept_vis (o); + if (o.failure_flag) + return UNKNOWN_NODEID; + + for (auto &seg : path.get_segments ()) + { + seg->accept_vis (o); + if (o.failure_flag) + return UNKNOWN_NODEID; + } + + // we only return the projection id for now since we need the type system to + // resolve the associated types in this path + return projection_resolved_id; + } + +private: + ResolveRelativeTypePath (CanonicalPath qualified_path) + : ResolveTypeToCanonicalPath (true, true) + { + result = qualified_path; + } + + static bool resolve_qual_seg (AST::QualifiedPathType &seg, + CanonicalPath &result); }; class ResolveType : public ResolverBase @@ -275,6 +336,15 @@ public: } } + void visit (AST::QualifiedPathInType &path) override + { + resolved_node + = ResolveRelativeTypePath::go (path, parent, + CanonicalPath::create_empty (), + canonicalize_type_with_generics); + ok = resolved_node != UNKNOWN_NODEID; + } + void visit (AST::ArrayType &type) override; void visit (AST::ReferenceType &type) override diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 9d79b36..fab70b5 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -243,8 +243,8 @@ Resolver::lookup_resolved_name (NodeId refId, NodeId *defId) void Resolver::insert_resolved_type (NodeId refId, NodeId defId) { - auto it = resolved_types.find (refId); - rust_assert (it == resolved_types.end ()); + // auto it = resolved_types.find (refId); + // rust_assert (it == resolved_types.end ()); resolved_types[refId] = defId; get_type_scope ().append_reference_for_def (refId, defId); @@ -560,17 +560,15 @@ ResolvePath::resolve_path (AST::QualifiedPathInExpression *expr) ResolveType::go (root_segment.get_type ().get (), root_segment.get_node_id (), canonicalize_type_with_generics); - bool canonicalize_type_args = true; bool type_resolve_generic_args = true; - CanonicalPath impl_type_seg = ResolveTypeToCanonicalPath::resolve (*root_segment.get_type ().get (), - canonicalize_type_args, + canonicalize_type_with_generics, type_resolve_generic_args); CanonicalPath trait_type_seg = ResolveTypeToCanonicalPath::resolve (root_segment.get_as_type_path (), - canonicalize_type_args, + canonicalize_type_with_generics, type_resolve_generic_args); CanonicalPath root_seg_path = TraitImplProjection::resolve (root_segment.get_node_id (), trait_type_seg, @@ -744,5 +742,48 @@ ResolveItem::resolve_extern_item (AST::ExternalItem *item) ResolveExternItem::go (item); } +// qualified path in type + +bool +ResolveRelativeTypePath::resolve_qual_seg (AST::QualifiedPathType &seg, + CanonicalPath &result) +{ + if (seg.is_error ()) + { + rust_error_at (seg.get_locus (), "segment has error: %s", + seg.as_string ().c_str ()); + return false; + } + bool include_generic_args_in_path = false; + + NodeId type_resolved_node + = ResolveType::go (seg.get_type ().get (), seg.get_node_id ()); + if (type_resolved_node == UNKNOWN_NODEID) + return false; + + CanonicalPath impl_type_seg + = ResolveTypeToCanonicalPath::resolve (*seg.get_type ().get (), + include_generic_args_in_path); + if (!seg.has_as_clause ()) + { + result = result.append (impl_type_seg); + return true; + } + + NodeId trait_resolved_node + = ResolveType::go (&seg.get_as_type_path (), seg.get_node_id ()); + if (trait_resolved_node == UNKNOWN_NODEID) + return false; + + CanonicalPath trait_type_seg + = ResolveTypeToCanonicalPath::resolve (seg.get_as_type_path (), + include_generic_args_in_path); + CanonicalPath projection + = TraitImplProjection::resolve (seg.get_node_id (), trait_type_seg, + impl_type_seg); + result = result.append (projection); + 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 60cd98a..dd51f83 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.h +++ b/gcc/rust/typecheck/rust-hir-path-probe.h @@ -276,6 +276,18 @@ protected: TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty (); + if (impl != nullptr) + { + HirId impl_block_id = impl->get_mappings ().get_hirid (); + AssociatedImplTrait *lookup_associated = nullptr; + bool found_impl_trait + = context->lookup_associated_trait_impl (impl_block_id, + &lookup_associated); + // see testsuite/rust/compile/torture/traits10.rs this can be false + if (found_impl_trait) + lookup_associated->setup_associated_types (); + } + // we can substitute the Self with the receiver here if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF) { diff --git a/gcc/rust/typecheck/rust-hir-trait-ref.h b/gcc/rust/typecheck/rust-hir-trait-ref.h index c86892e..f05ff0c 100644 --- a/gcc/rust/typecheck/rust-hir-trait-ref.h +++ b/gcc/rust/typecheck/rust-hir-trait-ref.h @@ -47,26 +47,7 @@ public: TraitItemReference (TraitItemReference const &other); - TraitItemReference &operator= (TraitItemReference const &other) - { - identifier = other.identifier; - optional_flag = other.optional_flag; - type = other.type; - hir_trait_item = other.hir_trait_item; - self = other.self; - locus = other.locus; - context = other.context; - - inherited_substitutions.clear (); - inherited_substitutions.reserve (other.inherited_substitutions.size ()); - for (size_t i = 0; i < other.inherited_substitutions.size (); i++) - inherited_substitutions.push_back (other.inherited_substitutions.at (i)); - - return *this; - } - - TraitItemReference (TraitItemReference &&other) = default; - TraitItemReference &operator= (TraitItemReference &&other) = default; + TraitItemReference &operator= (TraitItemReference const &other); static TraitItemReference error () { @@ -368,6 +349,7 @@ public: TyTy::BaseType *get_projected_type (const TraitItemReference *trait_item_ref, TyTy::BaseType *reciever, HirId ref, + HIR::GenericArgs &trait_generics, Location expr_locus); private: diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc index aeedf7e..be58840 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc @@ -58,7 +58,7 @@ ResolveTraitItemToRef::visit (HIR::TraitItemFunc &fn) resolved = TraitItemReference (identifier, is_optional, TraitItemReference::TraitItemType::FN, &fn, - self, substitutions, locus); + self, std::move (substitutions), locus); } // TraitItemReference items @@ -196,7 +196,7 @@ TraitItemReference::get_parent_trait_mappings () const TyTy::BaseType * AssociatedImplTrait::get_projected_type ( const TraitItemReference *trait_item_ref, TyTy::BaseType *receiver, HirId ref, - Location expr_locus) + HIR::GenericArgs &trait_generics, Location expr_locus) { TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty ()->clone (); @@ -219,11 +219,17 @@ AssociatedImplTrait::get_projected_type ( std::vector<TyTy::SubstitutionArg> mappings; mappings.push_back (TyTy::SubstitutionArg (param, receiver->clone ())); - Location locus; // FIXME - TyTy::SubstitutionArgumentMappings args (std::move (mappings), locus); + TyTy::SubstitutionArgumentMappings args (std::move (mappings), + expr_locus); trait_item_tyty = SubstMapperInternal::Resolve (trait_item_tyty, args); } + if (!trait_generics.is_empty ()) + { + trait_item_tyty + = SubstMapper::Resolve (trait_item_tyty, expr_locus, &trait_generics); + } + return trait_item_tyty; } diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.h b/gcc/rust/typecheck/rust-hir-trait-resolve.h index 0fe2406..365994f 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.h +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.h @@ -37,9 +37,9 @@ public: Resolve (HIR::TraitItem &item, TyTy::BaseType *self, std::vector<TyTy::SubstitutionParamMapping> substitutions) { - ResolveTraitItemToRef resolver (self, substitutions); + ResolveTraitItemToRef resolver (self, std::move (substitutions)); item.accept_vis (resolver); - return resolver.resolved; + return std::move (resolver.resolved); } void visit (HIR::TraitItemType &type) override; @@ -51,9 +51,9 @@ public: private: ResolveTraitItemToRef ( TyTy::BaseType *self, - std::vector<TyTy::SubstitutionParamMapping> substitutions) + std::vector<TyTy::SubstitutionParamMapping> &&substitutions) : TypeCheckBase (), resolved (TraitItemReference::error ()), self (self), - substitutions (substitutions) + substitutions (std::move (substitutions)) {} TraitItemReference resolved; @@ -146,8 +146,14 @@ private: std::vector<TraitItemReference> item_refs; for (auto &item : trait_reference->get_trait_items ()) { + // make a copy of the substs + std::vector<TyTy::SubstitutionParamMapping> item_subst; + for (auto &sub : substitutions) + item_subst.push_back (sub.clone ()); + TraitItemReference trait_item_ref - = ResolveTraitItemToRef::Resolve (*item.get (), self, substitutions); + = ResolveTraitItemToRef::Resolve (*item.get (), self, + std::move (item_subst)); item_refs.push_back (std::move (trait_item_ref)); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index 3d83523..59ea4ef 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -303,11 +303,12 @@ class TypeCheckImplItemWithTrait : public TypeCheckImplItem using Rust::Resolver::TypeCheckBase::visit; public: - static const TraitItemReference &Resolve (HIR::ImplItem *item, - TyTy::BaseType *self, - TraitReference &trait_reference) + static const TraitItemReference & + Resolve (HIR::ImplItem *item, TyTy::BaseType *self, + TraitReference &trait_reference, + std::vector<TyTy::SubstitutionParamMapping> substitutions) { - TypeCheckImplItemWithTrait resolver (self, trait_reference); + TypeCheckImplItemWithTrait resolver (self, trait_reference, substitutions); item->accept_vis (resolver); return resolver.resolved_trait_item; } @@ -383,7 +384,17 @@ public: trait_reference.get_name ().c_str ()); } - resolved_trait_item.associated_type_set (lookup); + rust_debug_loc (type.get_locus (), "type-alias within impl block"); + lookup->debug (); + + // its actually a projection, since we need a way to actually bind the + // generic substitutions to the type itself + TyTy::ProjectionType *projection = new TyTy::ProjectionType ( + type.get_mappings ().get_hirid (), lookup, &trait_reference, + resolved_trait_item.get_mappings ().get_defid (), substitutions); + + context->insert_type (type.get_mappings (), projection); + resolved_trait_item.associated_type_set (projection); } void visit (HIR::Function &function) override @@ -452,10 +463,12 @@ public: } private: - TypeCheckImplItemWithTrait (TyTy::BaseType *self, - TraitReference &trait_reference) + TypeCheckImplItemWithTrait ( + TyTy::BaseType *self, TraitReference &trait_reference, + std::vector<TyTy::SubstitutionParamMapping> substitutions) : TypeCheckImplItem (self), trait_reference (trait_reference), - resolved_trait_item (TraitItemReference::error_node ()) + resolved_trait_item (TraitItemReference::error_node ()), + substitutions (substitutions) { rust_assert (is_trait_impl_block ()); } @@ -464,6 +477,7 @@ private: TraitReference &trait_reference; TraitItemReference &resolved_trait_item; + std::vector<TyTy::SubstitutionParamMapping> substitutions; }; } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index ab32f57..476a961 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -43,6 +43,33 @@ public: void visit (HIR::ImplBlock &impl_block) override { + std::vector<TyTy::SubstitutionParamMapping> substitutions; + if (impl_block.has_generics ()) + { + for (auto &generic_param : impl_block.get_generic_params ()) + { + switch (generic_param.get ()->get_kind ()) + { + case HIR::GenericParam::GenericKind::LIFETIME: + // Skipping Lifetime completely until better handling. + break; + + case HIR::GenericParam::GenericKind::TYPE: { + TyTy::BaseType *l = nullptr; + bool ok = context->lookup_type ( + generic_param->get_mappings ().get_hirid (), &l); + if (ok && l->get_kind () == TyTy::TypeKind::PARAM) + { + substitutions.push_back (TyTy::SubstitutionParamMapping ( + static_cast<HIR::TypeParam &> (*generic_param), + static_cast<TyTy::ParamType *> (l))); + } + } + break; + } + } + } + TraitReference *trait_reference = &TraitReference::error_node (); if (impl_block.has_trait_ref ()) { @@ -72,7 +99,8 @@ public: { auto &trait_item_ref = TypeCheckImplItemWithTrait::Resolve (impl_item.get (), self, - *trait_reference); + *trait_reference, + substitutions); trait_item_refs.push_back (trait_item_ref); } } diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index 7b0e8ae..8b53e44 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -74,7 +74,6 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr) = context->lookup_associated_trait_impl (impl_block_id, &lookup_associated); rust_assert (found_impl_trait); - DefId resolved_item_id = UNKNOWN_DEFID; HIR::PathExprSegment &item_seg = expr.get_segments ().at (0); const TraitItemReference *trait_item_ref = nullptr; @@ -85,10 +84,14 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr) rust_error_at (item_seg.get_locus (), "unknown associated item"); return; } - resolved_item_id = trait_item_ref->get_mappings ().get_defid (); + HIR::GenericArgs trait_generics = qual_path_type.trait_has_generic_args () + ? qual_path_type.get_trait_generic_args () + : HIR::GenericArgs::create_empty (); + + lookup_associated->setup_associated_types (); infered = lookup_associated->get_projected_type ( - trait_item_ref, root, item_seg.get_mappings ().get_hirid (), + trait_item_ref, root, item_seg.get_mappings ().get_hirid (), trait_generics, item_seg.get_locus ()); // turbo-fish segment path::<ty> @@ -106,12 +109,6 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr) &item_seg.get_generic_args ()); } - TyTy::ProjectionType *projection - = new TyTy::ProjectionType (qual_path_type.get_mappings ().get_hirid (), - TyTy::TyVar (root->get_ref ()), trait_ref, - resolved_item_id, lookup_associated); - context->insert_type (qual_path_type.get_mappings (), projection); - // continue on as a path-in-expression NodeId root_resolved_node_id = trait_item_ref->get_mappings ().get_nodeid (); bool fully_resolved = expr.get_segments ().size () <= 1; @@ -340,6 +337,7 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id, candidates = PathProbeType::Probe (prev_segment, seg.get_segment (), false, probe_bounds, ignore_mandatory_trait_items); + if (candidates.size () == 0) { rust_error_at ( diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc new file mode 100644 index 0000000..b54a403 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -0,0 +1,225 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-hir-type-check-type.h" +#include "rust-hir-trait-resolve.h" + +namespace Rust { +namespace Resolver { + +void +TypeCheckType::visit (HIR::TypePath &path) +{ + // lookup the Node this resolves to + NodeId ref; + auto nid = path.get_mappings ().get_nodeid (); + if (!resolver->lookup_resolved_type (nid, &ref)) + { + rust_fatal_error (path.get_locus (), "failed to resolve node '%d' to HIR", + nid); + return; + } + + HirId hir_lookup; + if (!context->lookup_type_by_node_id (ref, &hir_lookup)) + { + rust_error_at (path.get_locus (), "failed to lookup HIR %d for node '%s'", + ref, path.as_string ().c_str ()); + return; + } + + TyTy::BaseType *lookup = nullptr; + if (!context->lookup_type (hir_lookup, &lookup)) + { + rust_error_at (path.get_locus (), "failed to lookup HIR TyTy"); + return; + } + + TyTy::BaseType *path_type = lookup->clone (); + path_type->set_ref (path.get_mappings ().get_hirid ()); + + HIR::TypePathSegment *final_seg = path.get_final_segment ().get (); + HIR::GenericArgs args = TypeCheckResolveGenericArguments::resolve (final_seg); + + bool is_big_self = final_seg->is_ident_only () + && (final_seg->as_string ().compare ("Self") == 0); + + if (path_type->needs_generic_substitutions ()) + { + if (is_big_self) + { + translated = path_type; + return; + } + + translated = SubstMapper::Resolve (path_type, path.get_locus (), &args); + if (translated->get_kind () != TyTy::TypeKind::ERROR + && mappings != nullptr) + { + check_for_unconstrained (args.get_type_args ()); + } + } + else if (!args.is_empty ()) + { + rust_error_at (path.get_locus (), + "TypePath %s declares generic arguments but " + "the type %s does not have any", + path.as_string ().c_str (), + translated->as_string ().c_str ()); + } + else + { + translated = path_type; + } +} + +void +TypeCheckType::visit (HIR::QualifiedPathInType &path) +{ + HIR::QualifiedPathType qual_path_type = path.get_path_type (); + TyTy::BaseType *root + = TypeCheckType::Resolve (qual_path_type.get_type ().get ()); + if (root->get_kind () == TyTy::TypeKind::ERROR) + { + rust_debug_loc (path.get_locus (), "failed to resolve the root"); + return; + } + + if (!qual_path_type.has_as_clause ()) + { + // then this is just a normal path-in-expression + NodeId root_resolved_node_id = UNKNOWN_NODEID; + bool ok = resolver->lookup_resolved_type ( + qual_path_type.get_type ()->get_mappings ().get_nodeid (), + &root_resolved_node_id); + rust_assert (ok); + + resolve_segments (root_resolved_node_id, path.get_segments (), 0, + translated, path.get_mappings (), path.get_locus ()); + } + + // Resolve the trait now + TraitReference *trait_ref + = TraitResolver::Resolve (*qual_path_type.get_trait ().get ()); + if (trait_ref->is_error ()) + return; + + // does this type actually implement this type-bound? + if (!TypeBoundsProbe::is_bound_satisfied_for_type (root, trait_ref)) + return; + + // we need resolve to the impl block + NodeId impl_resolved_id = UNKNOWN_NODEID; + bool ok = resolver->lookup_resolved_name ( + qual_path_type.get_mappings ().get_nodeid (), &impl_resolved_id); + rust_assert (ok); + + HirId impl_block_id; + ok = mappings->lookup_node_to_hir (path.get_mappings ().get_crate_num (), + impl_resolved_id, &impl_block_id); + rust_assert (ok); + + AssociatedImplTrait *lookup_associated = nullptr; + bool found_impl_trait + = context->lookup_associated_trait_impl (impl_block_id, &lookup_associated); + rust_assert (found_impl_trait); + + std::unique_ptr<HIR::TypePathSegment> &item_seg + = path.get_associated_segment (); + + const TraitItemReference *trait_item_ref = nullptr; + ok + = trait_ref->lookup_trait_item (item_seg->get_ident_segment ().as_string (), + &trait_item_ref); + if (!ok) + { + rust_error_at (item_seg->get_locus (), "unknown associated item"); + return; + } + + // project + lookup_associated->setup_associated_types (); + + HIR::GenericArgs trait_generics = qual_path_type.trait_has_generic_args () + ? qual_path_type.get_trait_generic_args () + : HIR::GenericArgs::create_empty (); + + translated = lookup_associated->get_projected_type ( + trait_item_ref, root, item_seg->get_mappings ().get_hirid (), + trait_generics, item_seg->get_locus ()); + + if (translated->get_kind () == TyTy::TypeKind::PLACEHOLDER) + { + // lets grab the actual projection type + TyTy::PlaceholderType *p + = static_cast<TyTy::PlaceholderType *> (translated); + if (p->can_resolve ()) + { + translated = p->resolve (); + } + } + + if (item_seg->get_type () == HIR::TypePathSegment::SegmentType::GENERIC) + { + HIR::TypePathSegmentGeneric &generic_seg + = static_cast<HIR::TypePathSegmentGeneric &> (*item_seg.get ()); + + // turbo-fish segment path::<ty> + if (generic_seg.has_generic_args ()) + { + if (!translated->can_substitute ()) + { + rust_error_at (item_seg->get_locus (), + "substitutions not supported for %s", + translated->as_string ().c_str ()); + translated + = new TyTy::ErrorType (path.get_mappings ().get_hirid ()); + return; + } + translated = SubstMapper::Resolve (translated, path.get_locus (), + &generic_seg.get_generic_args ()); + } + } + + // continue on as a path-in-expression + NodeId root_resolved_node_id = trait_item_ref->get_mappings ().get_nodeid (); + bool fully_resolved = path.get_segments ().empty (); + if (fully_resolved) + { + resolver->insert_resolved_name (path.get_mappings ().get_nodeid (), + root_resolved_node_id); + context->insert_receiver (path.get_mappings ().get_hirid (), root); + return; + } + + resolve_segments (root_resolved_node_id, path.get_segments (), 0, translated, + path.get_mappings (), path.get_locus ()); +} + +void +TypeCheckType::resolve_segments ( + NodeId root_resolved_node_id, + std::vector<std::unique_ptr<HIR::TypePathSegment>> &segments, size_t offset, + TyTy::BaseType *tyseg, const Analysis::NodeMapping &expr_mappings, + Location expr_locus) +{ + gcc_unreachable (); +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index 15eab25..c02a369 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -1,4 +1,3 @@ - // Copyright (C) 2020 Free Software Foundation, Inc. // This file is part of GCC. @@ -117,72 +116,9 @@ public: = new TyTy::TupleType (tuple.get_mappings ().get_hirid (), fields); } - void visit (HIR::TypePath &path) override - { - // lookup the Node this resolves to - NodeId ref; - auto nid = path.get_mappings ().get_nodeid (); - if (!resolver->lookup_resolved_type (nid, &ref)) - { - rust_fatal_error (path.get_locus (), - "failed to resolve node '%d' to HIR", nid); - return; - } - - HirId hir_lookup; - if (!context->lookup_type_by_node_id (ref, &hir_lookup)) - { - rust_error_at (path.get_locus (), - "failed to lookup HIR %d for node '%s'", ref, - path.as_string ().c_str ()); - return; - } - - TyTy::BaseType *lookup = nullptr; - if (!context->lookup_type (hir_lookup, &lookup)) - { - rust_error_at (path.get_locus (), "failed to lookup HIR TyTy"); - return; - } - - TyTy::BaseType *path_type = lookup->clone (); - path_type->set_ref (path.get_mappings ().get_hirid ()); - - HIR::TypePathSegment *final_seg = path.get_final_segment ().get (); - HIR::GenericArgs args - = TypeCheckResolveGenericArguments::resolve (final_seg); + void visit (HIR::TypePath &path) override; - bool is_big_self = final_seg->is_ident_only () - && (final_seg->as_string ().compare ("Self") == 0); - - if (path_type->needs_generic_substitutions ()) - { - if (is_big_self) - { - translated = path_type; - return; - } - - translated = SubstMapper::Resolve (path_type, path.get_locus (), &args); - if (translated->get_kind () != TyTy::TypeKind::ERROR - && mappings != nullptr) - { - check_for_unconstrained (args.get_type_args ()); - } - } - else if (!args.is_empty ()) - { - rust_error_at (path.get_locus (), - "TypePath %s declares generic arguments but " - "the type %s does not have any", - path.as_string ().c_str (), - translated->as_string ().c_str ()); - } - else - { - translated = path_type; - } - } + void visit (HIR::QualifiedPathInType &path) override; void visit (HIR::ArrayType &type) override; @@ -246,6 +182,12 @@ private: } } + void resolve_segments ( + NodeId root_resolved_node_id, + std::vector<std::unique_ptr<HIR::TypePathSegment>> &segments, size_t offset, + TyTy::BaseType *tyseg, const Analysis::NodeMapping &expr_mappings, + Location expr_locus); + std::vector<TyTy::SubstitutionParamMapping> *subst_mappings; TyTy::BaseType *translated; }; diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index 7f0e0ff..453f743 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -408,8 +408,9 @@ TraitItemReference::TraitItemReference ( HIR::TraitItem *hir_trait_item, TyTy::BaseType *self, std::vector<TyTy::SubstitutionParamMapping> substitutions, Location locus) : identifier (identifier), optional_flag (optional), type (type), - hir_trait_item (hir_trait_item), inherited_substitutions (substitutions), - locus (locus), self (self), context (TypeCheckContext::get ()) + hir_trait_item (hir_trait_item), + inherited_substitutions (std::move (substitutions)), locus (locus), + self (self), context (TypeCheckContext::get ()) {} TraitItemReference::TraitItemReference (TraitItemReference const &other) @@ -420,7 +421,28 @@ TraitItemReference::TraitItemReference (TraitItemReference const &other) inherited_substitutions.clear (); inherited_substitutions.reserve (other.inherited_substitutions.size ()); for (size_t i = 0; i < other.inherited_substitutions.size (); i++) - inherited_substitutions.push_back (other.inherited_substitutions.at (i)); + inherited_substitutions.push_back ( + other.inherited_substitutions.at (i).clone ()); +} + +TraitItemReference & +TraitItemReference::operator= (TraitItemReference const &other) +{ + identifier = other.identifier; + optional_flag = other.optional_flag; + type = other.type; + hir_trait_item = other.hir_trait_item; + self = other.self; + locus = other.locus; + context = other.context; + + inherited_substitutions.clear (); + inherited_substitutions.reserve (other.inherited_substitutions.size ()); + for (size_t i = 0; i < other.inherited_substitutions.size (); i++) + inherited_substitutions.push_back ( + other.inherited_substitutions.at (i).clone ()); + + return *this; } TyTy::BaseType * @@ -524,10 +546,13 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const context->insert_type (param.get_mappings (), param_tyty); } - return new TyTy::FnType (fn.get_mappings ().get_hirid (), - fn.get_mappings ().get_defid (), - function.get_function_name (), function.is_method (), - std::move (params), ret_type, substitutions); + auto resolved + = new TyTy::FnType (fn.get_mappings ().get_hirid (), + fn.get_mappings ().get_defid (), + function.get_function_name (), function.is_method (), + std::move (params), ret_type, substitutions); + context->insert_type (fn.get_mappings (), resolved); + return resolved; } } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index 27b7f12..491de85 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -42,6 +42,8 @@ public: TyTy::BaseType *type); bool lookup_type (HirId id, TyTy::BaseType **type); + void insert_implicit_type (HirId id, TyTy::BaseType *type); + void insert_type_by_node_id (NodeId ref, HirId id); bool lookup_type_by_node_id (NodeId ref, HirId *id); diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h index c7ea029..28cbeb8 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.h +++ b/gcc/rust/typecheck/rust-substitution-mapper.h @@ -90,6 +90,36 @@ public: 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::ADT); + 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; + } + + // nothing to do for these void visit (TyTy::InferType &) override { gcc_unreachable (); } void visit (TyTy::TupleType &) override { gcc_unreachable (); } void visit (TyTy::FnPtr &) override { gcc_unreachable (); } @@ -107,8 +137,6 @@ public: void visit (TyTy::ParamType &) override { gcc_unreachable (); } void visit (TyTy::StrType &) override { gcc_unreachable (); } void visit (TyTy::NeverType &) override { gcc_unreachable (); } - void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); } - void visit (TyTy::ProjectionType &) override { gcc_unreachable (); } private: SubstMapper (HirId ref, HIR::GenericArgs *generics, Location locus) @@ -177,6 +205,17 @@ public: resolved = type.handle_substitions (mappings); } + void visit (TyTy::PlaceholderType &type) override + { + rust_assert (type.can_resolve ()); + resolved = SubstMapperInternal::Resolve (type.resolve (), mappings); + } + + void visit (TyTy::ProjectionType &type) override + { + resolved = type.handle_substitions (mappings); + } + // nothing to do for these void visit (TyTy::InferType &) override { gcc_unreachable (); } void visit (TyTy::FnPtr &) override { gcc_unreachable (); } @@ -191,8 +230,6 @@ public: void visit (TyTy::CharType &) override { gcc_unreachable (); } void visit (TyTy::StrType &) override { gcc_unreachable (); } void visit (TyTy::NeverType &) override { gcc_unreachable (); } - void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); } - void visit (TyTy::ProjectionType &) override { gcc_unreachable (); } private: SubstMapperInternal (HirId ref, TyTy::SubstitutionArgumentMappings &mappings) diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc index ff1c627..95a16fa 100644 --- a/gcc/rust/typecheck/rust-tyctx.cc +++ b/gcc/rust/typecheck/rust-tyctx.cc @@ -83,6 +83,13 @@ TypeCheckContext::insert_type (const Analysis::NodeMapping &mappings, resolved[id] = 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) { diff --git a/gcc/rust/typecheck/rust-tyty-coercion.h b/gcc/rust/typecheck/rust-tyty-coercion.h index d30be7f..f12ffb4 100644 --- a/gcc/rust/typecheck/rust-tyty-coercion.h +++ b/gcc/rust/typecheck/rust-tyty-coercion.h @@ -46,6 +46,19 @@ public: other = p->resolve (); } } + else if (other->get_kind () == TypeKind::PLACEHOLDER) + { + PlaceholderType *p = static_cast<PlaceholderType *> (other); + if (p->can_resolve ()) + { + other = p->resolve (); + } + } + else if (other->get_kind () == TypeKind::PROJECTION) + { + ProjectionType *p = static_cast<ProjectionType *> (other); + other = p->get (); + } other->accept_vis (*this); if (resolved->get_kind () == TyTy::TypeKind::ERROR) diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 4d0b977..db7d8c0 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -76,6 +76,11 @@ public: other = p->resolve (); } } + else if (other->get_kind () == TypeKind::PROJECTION) + { + ProjectionType *p = static_cast<ProjectionType *> (other); + other = p->get (); + } other->accept_vis (*this); if (resolved->get_kind () == TyTy::TypeKind::ERROR) diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index e449b55..7eb717f 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -414,8 +414,6 @@ SubstitutionArgumentMappings SubstitutionRef::adjust_mappings_for_this ( SubstitutionArgumentMappings &mappings) { - Analysis::Mappings *mappings_table = Analysis::Mappings::get (); - std::vector<SubstitutionArg> resolved_mappings; for (size_t i = 0; i < substitutions.size (); i++) { @@ -442,20 +440,16 @@ SubstitutionRef::adjust_mappings_for_this ( } bool ok = !arg.is_error (); - if (!ok) + if (ok) { - rust_error_at (mappings_table->lookup_location ( - subst.get_param_ty ()->get_ref ()), - "failed to find parameter type: %s vs mappings [%s]", - subst.get_param_ty ()->as_string ().c_str (), - mappings.as_string ().c_str ()); - return SubstitutionArgumentMappings::error (); + SubstitutionArg adjusted (&subst, arg.get_tyty ()); + resolved_mappings.push_back (std::move (adjusted)); } - - 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_locus ()); } @@ -907,7 +901,9 @@ FnType::handle_substitions (SubstitutionArgumentMappings subst_mappings) bool ok = subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg); if (ok) - sub.fill_param_ty (arg.get_tyty (), subst_mappings.get_locus ()); + { + sub.fill_param_ty (arg.get_tyty (), subst_mappings.get_locus ()); + } } auto fty = fn->get_return_type (); @@ -2139,42 +2135,106 @@ ProjectionType::accept_vis (TyConstVisitor &vis) const std::string ProjectionType::as_string () const { - return "<Projection>"; + return "<Projection=" + subst_as_string () + "::" + base->as_string () + ">"; } BaseType * ProjectionType::unify (BaseType *other) { - gcc_unreachable (); - return nullptr; + return base->unify (other); } BaseType * ProjectionType::coerce (BaseType *other) { - gcc_unreachable (); - return nullptr; + return base->coerce (other); } BaseType * ProjectionType::cast (BaseType *other) { - gcc_unreachable (); - return nullptr; + return base->cast (other); } bool ProjectionType::can_eq (const BaseType *other, bool emit_errors) const { - gcc_unreachable (); - return false; + return base->can_eq (other, emit_errors); } BaseType * ProjectionType::clone () const { return new ProjectionType (get_ref (), get_ty_ref (), base, trait, item, - associated, get_combined_refs ()); + clone_substs (), used_arguments, + get_combined_refs ()); +} + +ProjectionType * +ProjectionType::handle_substitions (SubstitutionArgumentMappings subst_mappings) +{ + ProjectionType *projection = static_cast<ProjectionType *> (clone ()); + projection->set_ty_ref (mappings->get_next_hir_id ()); + projection->used_arguments = subst_mappings; + + auto context = Resolver::TypeCheckContext::get (); + context->insert_implicit_type (projection->get_ty_ref (), projection); + + for (auto &sub : projection->get_substs ()) + { + SubstitutionArg arg = SubstitutionArg::error (); + bool ok + = subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg); + if (ok) + sub.fill_param_ty (arg.get_tyty (), subst_mappings.get_locus ()); + } + + auto fty = projection->base; + bool is_param_ty = fty->get_kind () == TypeKind::PARAM; + if (is_param_ty) + { + ParamType *p = static_cast<ParamType *> (fty); + + SubstitutionArg arg = SubstitutionArg::error (); + bool ok = subst_mappings.get_argument_for_symbol (p, &arg); + if (ok) + { + auto argt = arg.get_tyty (); + bool arg_is_param = argt->get_kind () == TyTy::TypeKind::PARAM; + bool arg_is_concrete = argt->get_kind () != TyTy::TypeKind::INFER; + + if (arg_is_param || arg_is_concrete) + { + auto new_field = argt->clone (); + new_field->set_ref (fty->get_ref ()); + projection->base = new_field; + } + else + { + fty->set_ty_ref (argt->get_ref ()); + } + } + } + else if (fty->needs_generic_substitutions () + || fty->contains_type_parameters ()) + { + BaseType *concrete + = Resolver::SubstMapperInternal::Resolve (fty, subst_mappings); + + if (concrete == nullptr || concrete->get_kind () == TyTy::TypeKind::ERROR) + { + rust_error_at (subst_mappings.get_locus (), + "Failed to resolve field substitution type: %s", + fty->as_string ().c_str ()); + return nullptr; + } + + auto new_field = concrete->clone (); + new_field->set_ref (fty->get_ref ()); + projection->base = new_field; + } + + return projection; } // rust-tyty-call.h diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 743874a..0dfae37 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -1709,7 +1709,11 @@ public: std::string get_name () const override final { return as_string (); } - bool is_unit () const override { return true; } + bool is_unit () const override + { + rust_assert (can_resolve ()); + return resolve ()->is_unit (); + } std::string get_symbol () const { return symbol; } @@ -1723,26 +1727,38 @@ public: bool is_equal (const BaseType &other) const override; + bool contains_type_parameters () const override + { + rust_assert (can_resolve ()); + return resolve ()->contains_type_parameters (); + } + private: std::string symbol; }; -class ProjectionType : public BaseType +class ProjectionType : public BaseType, public SubstitutionRef { public: - ProjectionType (HirId ref, TyVar base, Resolver::TraitReference *trait, - DefId item, Resolver::AssociatedImplTrait *associated, + ProjectionType (HirId ref, BaseType *base, Resolver::TraitReference *trait, + DefId item, std::vector<SubstitutionParamMapping> subst_refs, + SubstitutionArgumentMappings generic_arguments + = SubstitutionArgumentMappings::error (), std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ref, TypeKind::PROJECTION, refs), base (base), - trait (trait), item (item), associated (associated) + : BaseType (ref, ref, TypeKind::PROJECTION, refs), + SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)), + base (base), trait (trait), item (item) {} - ProjectionType (HirId ref, HirId ty_ref, TyVar base, + ProjectionType (HirId ref, HirId ty_ref, BaseType *base, Resolver::TraitReference *trait, DefId item, - Resolver::AssociatedImplTrait *associated, + std::vector<SubstitutionParamMapping> subst_refs, + SubstitutionArgumentMappings generic_arguments + = SubstitutionArgumentMappings::error (), std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ty_ref, TypeKind::PROJECTION, refs), base (base), - trait (trait), item (item), associated (associated) + : BaseType (ref, ty_ref, TypeKind::PROJECTION, refs), + SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)), + base (base), trait (trait), item (item) {} void accept_vis (TyVisitor &vis) override; @@ -1761,11 +1777,32 @@ public: bool is_unit () const override { return false; } + bool needs_generic_substitutions () const override final + { + return needs_substitution (); + } + + bool supports_substitutions () const override final { return true; } + + bool has_subsititions_defined () const override final + { + return has_substitutions (); + } + + BaseType *get () { return base; } + + bool contains_type_parameters () const override + { + return base->contains_type_parameters (); + } + + ProjectionType * + handle_substitions (SubstitutionArgumentMappings mappings) override final; + private: - TyVar base; + BaseType *base; Resolver::TraitReference *trait; DefId item; - Resolver::AssociatedImplTrait *associated; }; } // namespace TyTy diff --git a/gcc/testsuite/rust/compile/torture/traits12.rs b/gcc/testsuite/rust/compile/torture/traits12.rs new file mode 100644 index 0000000..a55b965 --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/traits12.rs @@ -0,0 +1,29 @@ +trait Foo { + type A; + + fn test(a: Self::A) -> Self::A { + a + } +} + +struct Bar(i32); +// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 } + +impl Foo for Bar { + type A = i32; +} + +struct Baz(f32); +// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 } + +impl Foo for Baz { + type A = f32; +} + +fn main() { + let a: <Baz as Foo>::A; + a = 123f32; + + let b; + b = <Baz as Foo>::test(a); +} diff --git a/gcc/testsuite/rust/compile/torture/traits13.rs b/gcc/testsuite/rust/compile/torture/traits13.rs new file mode 100644 index 0000000..326f039 --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/traits13.rs @@ -0,0 +1,17 @@ +trait Trait { + const FOO: usize; + type Target; +} + +struct S; +// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 } + +impl Trait for S { + const FOO: usize = 0; + type Target = usize; +} + +fn main() { + let a: <S as Trait>::Target; + a = <S as Trait>::FOO; +} diff --git a/gcc/testsuite/rust/compile/torture/traits14.rs b/gcc/testsuite/rust/compile/torture/traits14.rs new file mode 100644 index 0000000..8bca0d5 --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/traits14.rs @@ -0,0 +1,23 @@ +trait Foo<T> { + type A; + + fn test(a: T) -> T { + a + } +} + +struct Bar<T>(T); +impl<T> Foo<T> for Bar<T> { + type A = T; +} + +pub fn main() { + let a; + a = Bar(123); + + let b: <Bar<i32> as Foo<i32>>::A; + b = 456; + + let c: <Bar<i32> as Foo<i32>>::A; + c = <Bar<i32> as Foo<i32>>::test(a.0); +} diff --git a/gcc/testsuite/rust/compile/torture/traits15.rs b/gcc/testsuite/rust/compile/torture/traits15.rs new file mode 100644 index 0000000..c8c40b7 --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/traits15.rs @@ -0,0 +1,23 @@ +trait Foo<T> { + type A; + + fn test(a: T, b: Self::A) -> (T, Self::A) { + (a, b) + } +} + +struct Bar<T>(T); +impl<T> Foo<T> for Bar<T> { + type A = T; +} + +pub fn main() { + let a; + a = Bar(123); + + let b: <Bar<i32> as Foo<i32>>::A; + b = 456; + + let c; + c = <Bar<i32> as Foo<i32>>::test(a.0, 123); +} |