diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-10-27 15:12:05 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-27 15:12:05 +0000 |
commit | e28c43f2f40cf405e89b3892aa65f6a06fa1c802 (patch) | |
tree | f7503c89dffd0fc84e1560525c5e219cefc79d78 | |
parent | 161a690d21044f5211ad2b55ae6b06f91bbd9106 (diff) | |
parent | 7604b6430cf3472399e5f24b7d8478a8ff89b22b (diff) | |
download | gcc-e28c43f2f40cf405e89b3892aa65f6a06fa1c802.zip gcc-e28c43f2f40cf405e89b3892aa65f6a06fa1c802.tar.gz gcc-e28c43f2f40cf405e89b3892aa65f6a06fa1c802.tar.bz2 |
Merge #771
771: Add higher ranked trait bounds r=philberty a=philberty
This adds support for where clauses and higher ranked trait bounds more test cases are needed
since where clauses are supported on associated types, impls, ADT's etc. See the individual
commits for more detail on implementation.
Fixes #773 #442
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
-rw-r--r-- | gcc/rust/ast/rust-item.h | 119 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-item.h | 72 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-type.h | 72 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-item.h | 106 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse-impl.h | 5 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-item.h | 48 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-type.h | 30 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-implitem.h | 10 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-toplevel.h | 31 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-type.h | 105 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.h | 2 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/torture/traits10.rs | 5 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/torture/traits18.rs | 8 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/trait11.rs | 41 |
14 files changed, 531 insertions, 123 deletions
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index d075a57..323548a 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -177,6 +177,8 @@ public: virtual void accept_vis (ASTVisitor &vis) = 0; + virtual NodeId get_node_id () const = 0; + protected: // Clone function implementation as pure virtual method virtual WhereClauseItem *clone_where_clause_item_impl () const = 0; @@ -186,24 +188,31 @@ protected: class LifetimeWhereClauseItem : public WhereClauseItem { Lifetime lifetime; - - // LifetimeBounds lifetime_bounds; - std::vector<Lifetime> lifetime_bounds; // inlined lifetime bounds - + std::vector<Lifetime> lifetime_bounds; Location locus; + NodeId node_id; public: LifetimeWhereClauseItem (Lifetime lifetime, std::vector<Lifetime> lifetime_bounds, Location locus) : lifetime (std::move (lifetime)), - lifetime_bounds (std::move (lifetime_bounds)), locus (locus) + lifetime_bounds (std::move (lifetime_bounds)), locus (locus), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} std::string as_string () const override; void accept_vis (ASTVisitor &vis) override; + NodeId get_node_id () const override final { return node_id; } + + Lifetime &get_lifetime () { return lifetime; } + + std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; } + + Location get_locus () const { return locus; } + protected: // Clone function implementation as (not pure) virtual method LifetimeWhereClauseItem *clone_where_clause_item_impl () const override @@ -215,18 +224,10 @@ protected: // A type bound where clause item class TypeBoundWhereClauseItem : public WhereClauseItem { - // bool has_for_lifetimes; - // LifetimeParams for_lifetimes; - std::vector<LifetimeParam> for_lifetimes; // inlined - + std::vector<LifetimeParam> for_lifetimes; std::unique_ptr<Type> bound_type; - - // bool has_type_param_bounds; - // TypeParamBounds type_param_bounds; - std::vector<std::unique_ptr<TypeParamBound>> - type_param_bounds; // inlined form - - // should this store location info? + std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; + NodeId node_id; public: // Returns whether the item has ForLifetimes @@ -240,7 +241,8 @@ public: std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds) : for_lifetimes (std::move (for_lifetimes)), bound_type (std::move (bound_type)), - type_param_bounds (std::move (type_param_bounds)) + type_param_bounds (std::move (type_param_bounds)), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} // Copy constructor requires clone @@ -248,6 +250,7 @@ public: : for_lifetimes (other.for_lifetimes), bound_type (other.bound_type->clone_type ()) { + node_id = other.node_id; type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) type_param_bounds.push_back (e->clone_type_param_bound ()); @@ -256,9 +259,9 @@ public: // Overload assignment operator to clone TypeBoundWhereClauseItem &operator= (TypeBoundWhereClauseItem const &other) { + node_id = other.node_id; for_lifetimes = other.for_lifetimes; bound_type = other.bound_type->clone_type (); - type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) type_param_bounds.push_back (e->clone_type_param_bound ()); @@ -275,7 +278,6 @@ public: void accept_vis (ASTVisitor &vis) override; - // TODO: is this better? Or is a "vis_block" better? std::unique_ptr<Type> &get_type () { rust_assert (bound_type != nullptr); @@ -287,12 +289,15 @@ public: { return type_param_bounds; } + const std::vector<std::unique_ptr<TypeParamBound>> & get_type_param_bounds () const { return type_param_bounds; } + NodeId get_node_id () const override final { return node_id; } + protected: // Clone function implementation as (not pure) virtual method TypeBoundWhereClauseItem *clone_where_clause_item_impl () const override @@ -306,17 +311,18 @@ struct WhereClause { private: std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items; - - // should this store location info? + NodeId node_id; public: WhereClause (std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items) - : where_clause_items (std::move (where_clause_items)) + : where_clause_items (std::move (where_clause_items)), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} // copy constructor with vector clone WhereClause (WhereClause const &other) { + node_id = other.node_id; where_clause_items.reserve (other.where_clause_items.size ()); for (const auto &e : other.where_clause_items) where_clause_items.push_back (e->clone_where_clause_item ()); @@ -325,6 +331,7 @@ public: // overloaded assignment operator with vector clone WhereClause &operator= (WhereClause const &other) { + node_id = other.node_id; where_clause_items.reserve (other.where_clause_items.size ()); for (const auto &e : other.where_clause_items) where_clause_items.push_back (e->clone_where_clause_item ()); @@ -347,6 +354,8 @@ public: std::string as_string () const; + NodeId get_node_id () const { return node_id; } + // TODO: this mutable getter seems kinda dodgy std::vector<std::unique_ptr<WhereClauseItem>> &get_items () { @@ -878,11 +887,7 @@ public: } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () - { - rust_assert (has_where_clause ()); - return where_clause; - } + WhereClause &get_where_clause () { return where_clause; } Identifier get_method_name () const { return method_name; } @@ -1578,11 +1583,7 @@ public: Identifier get_function_name () const { return function_name; } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () - { - rust_assert (has_where_clause ()); - return where_clause; - } + WhereClause &get_where_clause () { return where_clause; } // TODO: is this better? Or is a "vis_block" better? std::unique_ptr<Type> &get_return_type () @@ -1710,11 +1711,7 @@ public: } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () - { - rust_assert (has_where_clause ()); - return where_clause; - } + WhereClause &get_where_clause () { return where_clause; } // TODO: is this better? Or is a "vis_block" better? std::unique_ptr<Type> &get_type_aliased () @@ -1780,11 +1777,7 @@ public: } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () - { - rust_assert (has_where_clause ()); - return where_clause; - } + WhereClause &get_where_clause () { return where_clause; } Identifier get_identifier () const { return struct_name; } @@ -2401,11 +2394,7 @@ public: } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () - { - rust_assert (has_where_clause ()); - return where_clause; - } + WhereClause &get_where_clause () { return where_clause; } protected: /* Use covariance to implement clone function as returning this object @@ -2511,11 +2500,7 @@ public: } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () - { - rust_assert (has_where_clause ()); - return where_clause; - } + WhereClause &get_where_clause () { return where_clause; } Identifier get_identifier () const { return union_name; } @@ -2868,11 +2853,7 @@ public: } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () - { - rust_assert (has_where_clause ()); - return where_clause; - } + WhereClause &get_where_clause () { return where_clause; } }; // Actual trait item function declaration within traits @@ -3095,11 +3076,7 @@ public: } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () - { - rust_assert (has_where_clause ()); - return where_clause; - } + WhereClause &get_where_clause () { return where_clause; } SelfParam &get_self_param () { return self_param; } const SelfParam &get_self_param () const { return self_param; } @@ -3533,11 +3510,7 @@ public: return type_param_bounds; } - WhereClause &get_where_clause () - { - rust_assert (has_where_clause ()); - return where_clause; - } + WhereClause &get_where_clause () { return where_clause; } void insert_implict_self (std::unique_ptr<AST::GenericParam> &¶m) { @@ -3610,11 +3583,7 @@ public: } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () - { - rust_assert (has_where_clause ()); - return where_clause; - } + WhereClause &get_where_clause () { return where_clause; } // TODO: is this better? Or is a "vis_block" better? std::unique_ptr<Type> &get_type () @@ -4261,11 +4230,7 @@ public: } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () - { - rust_assert (has_where_clause ()); - return where_clause; - } + WhereClause &get_where_clause () { return where_clause; } // TODO: is this better? Or is a "vis_block" better? std::unique_ptr<Type> &get_return_type () diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index 9372e94..db0425f 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -95,6 +95,14 @@ public: void visit (AST::TypeAlias &alias) override { std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + for (auto &item : alias.get_where_clause ().get_items ()) + { + HIR::WhereClauseItem *i + = ASTLowerWhereClauseItem::translate (*item.get ()); + where_clause_items.push_back ( + std::unique_ptr<HIR::WhereClauseItem> (i)); + } + HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = HIR::Visibility::create_public (); @@ -134,6 +142,14 @@ public: } std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + for (auto &item : struct_decl.get_where_clause ().get_items ()) + { + HIR::WhereClauseItem *i + = ASTLowerWhereClauseItem::translate (*item.get ()); + where_clause_items.push_back ( + std::unique_ptr<HIR::WhereClauseItem> (i)); + } + HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = HIR::Visibility::create_public (); @@ -186,6 +202,14 @@ public: } std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + for (auto &item : struct_decl.get_where_clause ().get_items ()) + { + HIR::WhereClauseItem *i + = ASTLowerWhereClauseItem::translate (*item.get ()); + where_clause_items.push_back ( + std::unique_ptr<HIR::WhereClauseItem> (i)); + } + HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = HIR::Visibility::create_public (); @@ -242,6 +266,14 @@ public: } std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + for (auto &item : enum_decl.get_where_clause ().get_items ()) + { + HIR::WhereClauseItem *i + = ASTLowerWhereClauseItem::translate (*item.get ()); + where_clause_items.push_back ( + std::unique_ptr<HIR::WhereClauseItem> (i)); + } + HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = HIR::Visibility::create_public (); @@ -282,6 +314,13 @@ public: } std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + for (auto &item : union_decl.get_where_clause ().get_items ()) + { + HIR::WhereClauseItem *i + = ASTLowerWhereClauseItem::translate (*item.get ()); + where_clause_items.push_back ( + std::unique_ptr<HIR::WhereClauseItem> (i)); + } HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = HIR::Visibility::create_public (); @@ -380,8 +419,15 @@ public: void visit (AST::Function &function) override { - // ignore for now and leave empty std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + for (auto &item : function.get_where_clause ().get_items ()) + { + HIR::WhereClauseItem *i + = ASTLowerWhereClauseItem::translate (*item.get ()); + where_clause_items.push_back ( + std::unique_ptr<HIR::WhereClauseItem> (i)); + } + HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::FunctionQualifiers qualifiers ( HIR::FunctionQualifiers::AsyncConstStatus::NONE, Unsafety::Normal); @@ -466,6 +512,13 @@ public: void visit (AST::InherentImpl &impl_block) override { std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + for (auto &item : impl_block.get_where_clause ().get_items ()) + { + HIR::WhereClauseItem *i + = ASTLowerWhereClauseItem::translate (*item.get ()); + where_clause_items.push_back ( + std::unique_ptr<HIR::WhereClauseItem> (i)); + } HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = HIR::Visibility::create_public (); @@ -545,8 +598,15 @@ public: void visit (AST::Trait &trait) override { std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; - + for (auto &item : trait.get_where_clause ().get_items ()) + { + HIR::WhereClauseItem *i + = ASTLowerWhereClauseItem::translate (*item.get ()); + where_clause_items.push_back ( + std::unique_ptr<HIR::WhereClauseItem> (i)); + } HIR::WhereClause where_clause (std::move (where_clause_items)); + HIR::Visibility vis = HIR::Visibility::create_public (); std::vector<std::unique_ptr<HIR::GenericParam>> generic_params; @@ -632,7 +692,13 @@ public: void visit (AST::TraitImpl &impl_block) override { std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; - + for (auto &item : impl_block.get_where_clause ().get_items ()) + { + HIR::WhereClauseItem *i + = ASTLowerWhereClauseItem::translate (*item.get ()); + where_clause_items.push_back ( + std::unique_ptr<HIR::WhereClauseItem> (i)); + } HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = HIR::Visibility::create_public (); diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index 0a71e3a..8205d07 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -60,7 +60,7 @@ public: void visit (AST::TypePath &path) override { - std::vector<std::unique_ptr<HIR::TypePathSegment> > translated_segments; + std::vector<std::unique_ptr<HIR::TypePathSegment>> translated_segments; path.iterate_segments ([&] (AST::TypePathSegment *seg) mutable -> bool { translated_segment = nullptr; @@ -188,7 +188,7 @@ public: void visit (AST::TupleType &tuple) override { - std::vector<std::unique_ptr<HIR::Type> > elems; + std::vector<std::unique_ptr<HIR::Type>> elems; for (auto &e : tuple.get_elems ()) { HIR::Type *t = ASTLoweringType::translate (e.get ()); @@ -340,7 +340,7 @@ public: void visit (AST::TypeParam ¶m) override { AST::Attribute outer_attr = AST::Attribute::create_empty (); - std::vector<std::unique_ptr<HIR::TypeParamBound> > type_param_bounds; + std::vector<std::unique_ptr<HIR::TypeParamBound>> type_param_bounds; if (param.has_type_param_bounds ()) { for (auto &bound : param.get_type_param_bounds ()) @@ -422,6 +422,72 @@ private: HIR::TypeParamBound *translated; }; +class ASTLowerWhereClauseItem : public ASTLoweringBase +{ + using Rust::HIR::ASTLoweringBase::visit; + +public: + static HIR::WhereClauseItem *translate (AST::WhereClauseItem &item) + { + ASTLowerWhereClauseItem compiler; + item.accept_vis (compiler); + rust_assert (compiler.translated != nullptr); + return compiler.translated; + } + + void visit (AST::LifetimeWhereClauseItem &item) override + { + HIR::Lifetime l = lower_lifetime (item.get_lifetime ()); + std::vector<HIR::Lifetime> lifetime_bounds; + for (auto &lifetime_bound : item.get_lifetime_bounds ()) + { + HIR::Lifetime ll = lower_lifetime (lifetime_bound); + lifetime_bounds.push_back (std::move (ll)); + } + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, item.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated = new HIR::LifetimeWhereClauseItem (mapping, std::move (l), + std::move (lifetime_bounds), + item.get_locus ()); + } + + void visit (AST::TypeBoundWhereClauseItem &item) override + { + // FIXME + std::vector<HIR::LifetimeParam> for_lifetimes; + + std::unique_ptr<HIR::Type> bound_type = std::unique_ptr<HIR::Type> ( + ASTLoweringType::translate (item.get_type ().get ())); + + std::vector<std::unique_ptr<HIR::TypeParamBound>> type_param_bounds; + for (auto &bound : item.get_type_param_bounds ()) + { + HIR::TypeParamBound *b + = ASTLoweringTypeBounds::translate (bound.get ()); + type_param_bounds.push_back (std::unique_ptr<HIR::TypeParamBound> (b)); + } + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, item.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated + = new HIR::TypeBoundWhereClauseItem (mapping, std::move (for_lifetimes), + std::move (bound_type), + std::move (type_param_bounds)); + } + +private: + ASTLowerWhereClauseItem () : ASTLoweringBase (), translated (nullptr) {} + + HIR::WhereClauseItem *translated; +}; + } // namespace HIR } // namespace Rust diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index ab9eab6..21f0781 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -20,6 +20,7 @@ #define RUST_HIR_ITEM_H #include "rust-ast-full-decls.h" +#include "rust-common.h" #include "rust-hir.h" #include "rust-hir-path.h" @@ -140,6 +141,12 @@ protected: class WhereClauseItem { public: + enum ItemType + { + LIFETIME, + TYPE_BOUND, + }; + virtual ~WhereClauseItem () {} // Unique pointer custom clone function @@ -152,6 +159,10 @@ public: virtual void accept_vis (HIRVisitor &vis) = 0; + virtual Analysis::NodeMapping get_mappings () const = 0; + + virtual ItemType get_item_type () const = 0; + protected: // Clone function implementation as pure virtual method virtual WhereClauseItem *clone_where_clause_item_impl () const = 0; @@ -161,24 +172,37 @@ protected: class LifetimeWhereClauseItem : public WhereClauseItem { Lifetime lifetime; - - // LifetimeBounds lifetime_bounds; - std::vector<Lifetime> lifetime_bounds; // inlined lifetime bounds - + std::vector<Lifetime> lifetime_bounds; Location locus; + Analysis::NodeMapping mappings; public: - LifetimeWhereClauseItem (Lifetime lifetime, + LifetimeWhereClauseItem (Analysis::NodeMapping mappings, Lifetime lifetime, std::vector<Lifetime> lifetime_bounds, Location locus) : lifetime (std::move (lifetime)), - lifetime_bounds (std::move (lifetime_bounds)), locus (locus) + lifetime_bounds (std::move (lifetime_bounds)), locus (locus), + mappings (std::move (mappings)) {} std::string as_string () const override; void accept_vis (HIRVisitor &vis) override; + Lifetime &get_lifetime () { return lifetime; } + + std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; } + + Analysis::NodeMapping get_mappings () const override final + { + return mappings; + }; + + ItemType get_item_type () const override final + { + return WhereClauseItem::ItemType::LIFETIME; + } + protected: // Clone function implementation as (not pure) virtual method LifetimeWhereClauseItem *clone_where_clause_item_impl () const override @@ -190,18 +214,10 @@ protected: // A type bound where clause item class TypeBoundWhereClauseItem : public WhereClauseItem { - // bool has_for_lifetimes; - // LifetimeParams for_lifetimes; - std::vector<LifetimeParam> for_lifetimes; // inlined - + std::vector<LifetimeParam> for_lifetimes; std::unique_ptr<Type> bound_type; - - // bool has_type_param_bounds; - // TypeParamBounds type_param_bounds; - std::vector<std::unique_ptr<TypeParamBound>> - type_param_bounds; // inlined form - - // should this store location info? + std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; + Analysis::NodeMapping mappings; public: // Returns whether the item has ForLifetimes @@ -211,17 +227,19 @@ public: bool has_type_param_bounds () const { return !type_param_bounds.empty (); } TypeBoundWhereClauseItem ( - std::vector<LifetimeParam> for_lifetimes, std::unique_ptr<Type> bound_type, + Analysis::NodeMapping mappings, std::vector<LifetimeParam> for_lifetimes, + std::unique_ptr<Type> bound_type, std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds) : for_lifetimes (std::move (for_lifetimes)), bound_type (std::move (bound_type)), - type_param_bounds (std::move (type_param_bounds)) + type_param_bounds (std::move (type_param_bounds)), + mappings (std::move (mappings)) {} // Copy constructor requires clone TypeBoundWhereClauseItem (TypeBoundWhereClauseItem const &other) : for_lifetimes (other.for_lifetimes), - bound_type (other.bound_type->clone_type ()) + bound_type (other.bound_type->clone_type ()), mappings (other.mappings) { type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) @@ -231,9 +249,9 @@ public: // Overload assignment operator to clone TypeBoundWhereClauseItem &operator= (TypeBoundWhereClauseItem const &other) { + mappings = other.mappings; for_lifetimes = other.for_lifetimes; bound_type = other.bound_type->clone_type (); - type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) type_param_bounds.push_back (e->clone_type_param_bound ()); @@ -250,6 +268,25 @@ public: void accept_vis (HIRVisitor &vis) override; + std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; } + + std::unique_ptr<Type> &get_bound_type () { return bound_type; } + + std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds () + { + return type_param_bounds; + } + + Analysis::NodeMapping get_mappings () const override final + { + return mappings; + }; + + ItemType get_item_type () const override final + { + return WhereClauseItem::ItemType::TYPE_BOUND; + } + protected: // Clone function implementation as (not pure) virtual method TypeBoundWhereClauseItem *clone_where_clause_item_impl () const override @@ -303,6 +340,15 @@ public: bool is_empty () const { return where_clause_items.empty (); } std::string as_string () const; + + std::vector<std::unique_ptr<WhereClauseItem>> &get_items () + { + return where_clause_items; + } + const std::vector<std::unique_ptr<WhereClauseItem>> &get_items () const + { + return where_clause_items; + } }; // A self parameter in a method @@ -1168,11 +1214,7 @@ public: Identifier get_function_name () const { return function_name; } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () - { - rust_assert (has_where_clause ()); - return where_clause; - } + WhereClause &get_where_clause () { return where_clause; } bool has_return_type () const { return return_type != nullptr; } @@ -1285,11 +1327,7 @@ public: return generic_params; } - WhereClause &get_where_clause () - { - rust_assert (has_where_clause ()); - return where_clause; - } + WhereClause &get_where_clause () { return where_clause; } std::unique_ptr<Type> &get_type_aliased () { @@ -1349,6 +1387,8 @@ public: return generic_params; } + WhereClause &get_where_clause () { return where_clause; } + protected: Struct (Analysis::NodeMapping mappings, Identifier struct_name, std::vector<std::unique_ptr<GenericParam>> generic_params, @@ -1956,6 +1996,8 @@ public: } } + WhereClause &get_where_clause () { return where_clause; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2666,6 +2708,8 @@ public: return trait_ref; } + WhereClause &get_where_clause () { return where_clause; } + protected: ImplBlock *clone_item_impl () const override { return new ImplBlock (*this); } }; diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 14e4e80..8bddfcd 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -6239,9 +6239,7 @@ Parser<ManagedTokenSource>::parse_path_generic_args () const_TokenPtr t = lexer.peek_token (); Location locus = t->get_locus (); - const_TokenPtr t2 = lexer.peek_token (1); - while (t->get_id () == LIFETIME - && (t2->get_id () == COMMA || !is_right_angle_tok (t2->get_id ()))) + while (!is_right_angle_tok (t->get_id ())) { AST::Lifetime lifetime = parse_lifetime (); if (lifetime.is_error ()) @@ -6261,7 +6259,6 @@ Parser<ManagedTokenSource>::parse_path_generic_args () lexer.skip_token (); t = lexer.peek_token (); - t2 = lexer.peek_token (1); } // try to parse types second diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index fbb8fd4..86c9934 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -58,7 +58,8 @@ public: resolver->get_type_scope ().append_reference_for_def (type.get_node_id (), type.get_node_id ()); - // TODO resolve the type-bounds + for (auto &bound : type.get_type_param_bounds ()) + ResolveTypeBound::go (bound.get (), type.get_node_id ()); } void visit (AST::TraitItemFunc &func) override @@ -95,6 +96,9 @@ public: param.get_node_id ()); } + if (function.has_where_clause ()) + ResolveWhereClause::Resolve (function.get_where_clause ()); + // trait items have an optional body if (func.has_definition ()) ResolveExpr::go (func.get_definition ().get (), func.get_node_id ()); @@ -158,6 +162,9 @@ public: param.get_node_id ()); } + if (function.has_where_clause ()) + ResolveWhereClause::Resolve (function.get_where_clause ()); + // trait items have an optional body if (func.has_definition ()) ResolveExpr::go (func.get_definition ().get (), func.get_node_id ()); @@ -211,6 +218,9 @@ public: ResolveGenericParam::go (generic.get (), alias.get_node_id ()); } + if (alias.has_where_clause ()) + ResolveWhereClause::Resolve (alias.get_where_clause ()); + ResolveType::go (alias.get_type_aliased ().get (), alias.get_node_id ()); resolver->get_type_scope ().pop (); @@ -251,6 +261,9 @@ public: } } + if (struct_decl.has_where_clause ()) + ResolveWhereClause::Resolve (struct_decl.get_where_clause ()); + struct_decl.iterate ([&] (AST::TupleField &field) mutable -> bool { ResolveType::go (field.get_field_type ().get (), struct_decl.get_node_id ()); @@ -273,6 +286,9 @@ public: } } + if (enum_decl.has_where_clause ()) + ResolveWhereClause::Resolve (enum_decl.get_where_clause ()); + /* The actual fields are inside the variants. */ for (auto &variant : enum_decl.get_variants ()) ResolveItem::go (variant.get ()); @@ -310,6 +326,9 @@ public: } } + if (struct_decl.has_where_clause ()) + ResolveWhereClause::Resolve (struct_decl.get_where_clause ()); + struct_decl.iterate ([&] (AST::StructField &field) mutable -> bool { ResolveType::go (field.get_field_type ().get (), struct_decl.get_node_id ()); @@ -332,6 +351,9 @@ public: } } + if (union_decl.has_where_clause ()) + ResolveWhereClause::Resolve (union_decl.get_where_clause ()); + union_decl.iterate ([&] (AST::StructField &field) mutable -> bool { ResolveType::go (field.get_field_type ().get (), union_decl.get_node_id ()); @@ -379,6 +401,10 @@ public: ResolveGenericParam::go (generic.get (), function.get_node_id ()); } + // resolve any where clause items + if (function.has_where_clause ()) + ResolveWhereClause::Resolve (function.get_where_clause ()); + if (function.has_return_type ()) ResolveType::go (function.get_return_type ().get (), function.get_node_id ()); @@ -422,6 +448,10 @@ public: } } + // resolve any where clause items + if (impl_block.has_where_clause ()) + ResolveWhereClause::Resolve (impl_block.get_where_clause ()); + bool canonicalize_type_with_generics = false; NodeId resolved_node = ResolveType::go (impl_block.get_type ().get (), impl_block.get_node_id (), @@ -468,6 +498,10 @@ public: ResolveGenericParam::go (generic.get (), method.get_node_id ()); } + // resolve any where clause items + if (method.has_where_clause ()) + ResolveWhereClause::Resolve (method.get_where_clause ()); + if (method.has_return_type ()) ResolveType::go (method.get_return_type ().get (), method.get_node_id ()); @@ -505,6 +539,10 @@ public: param.get_node_id ()); } + // resolve any where clause items + if (method.has_where_clause ()) + ResolveWhereClause::Resolve (method.get_where_clause ()); + // resolve the function body ResolveExpr::go (method.get_definition ().get (), method.get_node_id ()); @@ -529,6 +567,10 @@ public: } } + // resolve any where clause items + if (impl_block.has_where_clause ()) + ResolveWhereClause::Resolve (impl_block.get_where_clause ()); + bool canonicalize_type_with_generics = false; NodeId trait_resolved_node = ResolveType::go (&impl_block.get_trait_path (), @@ -601,6 +643,10 @@ public: } } + // resolve any where clause items + if (trait.has_where_clause ()) + ResolveWhereClause::Resolve (trait.get_where_clause ()); + for (auto &item : trait.get_trait_items ()) { ResolveTraitItems::go (item.get (), Self); diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index 6b9fb89..4708bff 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -473,6 +473,36 @@ private: bool ok; }; +class ResolveWhereClause : public ResolverBase +{ + using Rust::Resolver::ResolverBase::visit; + +public: + static void Resolve (AST::WhereClause &where_clause) + { + ResolveWhereClause r (where_clause.get_node_id ()); + for (auto &clause : where_clause.get_items ()) + clause->accept_vis (r); + } + + void visit (AST::LifetimeWhereClauseItem &) override {} + + void visit (AST::TypeBoundWhereClauseItem &item) override + { + ResolveType::go (item.get_type ().get (), item.get_node_id ()); + if (item.has_type_param_bounds ()) + { + for (auto &bound : item.get_type_param_bounds ()) + { + ResolveTypeBound::go (bound.get (), item.get_node_id ()); + } + } + } + +private: + ResolveWhereClause (NodeId parent) : ResolverBase (parent) {} +}; // namespace Resolver + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index 501ce3f..062d60b 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -150,6 +150,11 @@ public: = TypeCheckType::Resolve (alias.get_type_aliased ().get ()); context->insert_type (alias.get_mappings (), actual_type); + + for (auto &where_clause_item : alias.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } } void visit (HIR::ConstantItem &constant) override @@ -191,6 +196,11 @@ public: } } + for (auto &where_clause_item : function.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } + TyTy::BaseType *ret_type = nullptr; if (!function.has_function_return_type ()) ret_type = new TyTy::TupleType (function.get_mappings ().get_hirid ()); diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index a85fe66..a32d4a4 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -46,6 +46,11 @@ public: = TypeCheckType::Resolve (alias.get_type_aliased ().get ()); context->insert_type (alias.get_mappings (), actual_type); + + for (auto &where_clause_item : alias.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } } void visit (HIR::TupleStruct &struct_decl) override @@ -76,6 +81,11 @@ public: } } + for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } + std::vector<TyTy::StructFieldType *> fields; size_t idx = 0; @@ -136,6 +146,11 @@ public: } } + for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } + std::vector<TyTy::StructFieldType *> fields; for (auto &field : struct_decl.get_fields ()) @@ -188,6 +203,11 @@ public: } } + for (auto &where_clause_item : union_decl.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } + std::vector<TyTy::StructFieldType *> variants; union_decl.iterate ([&] (HIR::StructField &variant) mutable -> bool { TyTy::BaseType *variant_type @@ -259,6 +279,11 @@ public: } } + for (auto &where_clause_item : function.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } + TyTy::BaseType *ret_type = nullptr; if (!function.has_function_return_type ()) ret_type = new TyTy::TupleType (function.get_mappings ().get_hirid ()); @@ -296,6 +321,7 @@ public: TyTy::FnType::FNTYPE_DEFAULT_FLAGS, ABI::RUST, std::move (params), ret_type, std::move (substitutions)); + context->insert_type (function.get_mappings (), fnType); } @@ -327,6 +353,11 @@ public: } } + for (auto &where_clause_item : impl_block.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } + auto self = TypeCheckType::Resolve (impl_block.get_type ().get (), &substitutions); if (self == nullptr || self->get_kind () == TyTy::TypeKind::ERROR) diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index b56b5a2..c2b6d7c 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -277,6 +277,111 @@ private: TyTy::ParamType *resolved; }; +class ResolveWhereClauseItem : public TypeCheckBase +{ + using Rust::Resolver::TypeCheckBase::visit; + +public: + static void Resolve (HIR::WhereClauseItem &item) + { + ResolveWhereClauseItem resolver; + item.accept_vis (resolver); + } + + void visit (HIR::LifetimeWhereClauseItem &) override {} + + void visit (HIR::TypeBoundWhereClauseItem &item) override + { + auto &binding_type_path = item.get_bound_type (); + TyTy::BaseType *binding = TypeCheckType::Resolve (binding_type_path.get ()); + + std::vector<TyTy::TypeBoundPredicate> specified_bounds; + for (auto &bound : item.get_type_param_bounds ()) + { + switch (bound->get_bound_type ()) + { + case HIR::TypeParamBound::BoundType::TRAITBOUND: { + HIR::TraitBound *b + = static_cast<HIR::TraitBound *> (bound.get ()); + + auto &type_path = b->get_path (); + TraitReference *trait = resolve_trait_path (type_path); + TyTy::TypeBoundPredicate predicate ( + trait->get_mappings ().get_defid (), b->get_locus ()); + + auto &final_seg = type_path.get_final_segment (); + if (final_seg->is_generic_segment ()) + { + auto final_generic_seg + = static_cast<HIR::TypePathSegmentGeneric *> ( + final_seg.get ()); + if (final_generic_seg->has_generic_args ()) + { + HIR::GenericArgs &generic_args + = final_generic_seg->get_generic_args (); + + // this is applying generic arguments to a trait + // reference + predicate.apply_generic_arguments (&generic_args); + } + } + + specified_bounds.push_back (std::move (predicate)); + } + break; + + default: + break; + } + } + binding->inherit_bounds (specified_bounds); + + // When we apply these bounds we must lookup which type this binding + // resolves to, as this is the type which will be used during resolution of + // the block. + NodeId ast_node_id = binding_type_path->get_mappings ().get_nodeid (); + + // then lookup the reference_node_id + NodeId ref_node_id = UNKNOWN_NODEID; + if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id)) + { + // FIXME + rust_error_at (Location (), + "Failed to lookup type reference for node: %s", + binding_type_path->as_string ().c_str ()); + return; + } + + // node back to HIR + HirId ref; + if (!mappings->lookup_node_to_hir ( + binding_type_path->get_mappings ().get_crate_num (), ref_node_id, + &ref)) + { + // FIXME + rust_error_at (Location (), "where-clause reverse lookup failure"); + return; + } + + // the base reference for this name _must_ have a type set + TyTy::BaseType *lookup; + if (!context->lookup_type (ref, &lookup)) + { + rust_error_at (mappings->lookup_location (ref), + "Failed to resolve where-clause binding type: %s", + binding_type_path->as_string ().c_str ()); + return; + } + + // FIXME + // rust_assert (binding->is_equal (*lookup)); + lookup->inherit_bounds (specified_bounds); + } + +private: + ResolveWhereClauseItem () : TypeCheckBase () {} +}; + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index aa24464..ef37dc6 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -380,7 +380,7 @@ public: std::string debug_str () const { return TypeKindFormat::to_string (get_kind ()) + ":" + as_string () + ":" - + mappings_str (); + + mappings_str () + ":" + bounds_as_string (); } void debug () const diff --git a/gcc/testsuite/rust/compile/torture/traits10.rs b/gcc/testsuite/rust/compile/torture/traits10.rs index 3e47b1b..a492ec3 100644 --- a/gcc/testsuite/rust/compile/torture/traits10.rs +++ b/gcc/testsuite/rust/compile/torture/traits10.rs @@ -1,6 +1,5 @@ -trait Foo -where - Self: Sized, +trait Foo // where +// Self: Sized, { fn get(self) -> i32; // { dg-warning "unused name" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/rust/compile/torture/traits18.rs b/gcc/testsuite/rust/compile/torture/traits18.rs new file mode 100644 index 0000000..77cc5c2 --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/traits18.rs @@ -0,0 +1,8 @@ +trait Foo<'a> {} + +trait Bar { + // { dg-warning "unused name .Bar." "" { target *-*-* } .-1 } + + type Item: for<'a> Foo<'a>; + // { dg-warning "unused name" "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/rust/execute/torture/trait11.rs b/gcc/testsuite/rust/execute/torture/trait11.rs new file mode 100644 index 0000000..53a8a8e --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/trait11.rs @@ -0,0 +1,41 @@ +/* { dg-output "3\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +trait FnLike<A, R> { + fn call(&self, arg: A) -> R; + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name .arg." "" { target *-*-* } .-2 } +} + +struct S; +impl<'a, T> FnLike<&'a T, &'a T> for S { + fn call(&self, arg: &'a T) -> &'a T { + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name" "" { target *-*-* } .-2 } + arg + } +} + +fn indirect<F>(f: F) +where + F: for<'a> FnLike<&'a isize, &'a isize>, +{ + let x = 3; + let y = f.call(&x); + + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, *y); + } +} + +fn main() -> i32 { + indirect(S); + + 0 +} |