aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-10-27 15:12:05 +0000
committerGitHub <noreply@github.com>2021-10-27 15:12:05 +0000
commite28c43f2f40cf405e89b3892aa65f6a06fa1c802 (patch)
treef7503c89dffd0fc84e1560525c5e219cefc79d78
parent161a690d21044f5211ad2b55ae6b06f91bbd9106 (diff)
parent7604b6430cf3472399e5f24b7d8478a8ff89b22b (diff)
downloadgcc-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.h119
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.h72
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.h72
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h106
-rw-r--r--gcc/rust/parse/rust-parse-impl.h5
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.h48
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.h30
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.h10
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-toplevel.h31
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h105
-rw-r--r--gcc/rust/typecheck/rust-tyty.h2
-rw-r--r--gcc/testsuite/rust/compile/torture/traits10.rs5
-rw-r--r--gcc/testsuite/rust/compile/torture/traits18.rs8
-rw-r--r--gcc/testsuite/rust/execute/torture/trait11.rs41
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> &&param)
{
@@ -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 &param) 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
+}