diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index d8713071c4c3..851f7ea4b6f6 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -3050,6 +3050,18 @@ TraitItemType::as_string () const str += "\ntype " + name.as_string (); + if (has_generics ()) + { + str += "<"; + for (size_t i = 0; i < generic_params.size (); i++) + { + if (i > 0) + str += ", "; + str += generic_params[i]->as_string (); + } + str += ">"; + } + str += "\n Type param bounds: "; if (!has_type_param_bounds ()) { diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 8a7e618b05ce..8610ade830c1 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1891,7 +1891,6 @@ struct MacroInvocData { parsed_items = std::move (new_items); } - // TODO: mutable getter seems kinda dodgy std::vector> &get_meta_items () { return parsed_items; diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 7aea763bd12e..3e3735c3ece6 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -2726,21 +2726,28 @@ class TraitItemType : public TraitItem Identifier name; + // Generic parameters for GATs (Generic Associated Types) + std::vector> generic_params; + // bool has_type_param_bounds; // TypeParamBounds type_param_bounds; std::vector> type_param_bounds; // inlined form public: + bool has_generics () const { return !generic_params.empty (); } + // Returns whether trait item type has type param bounds. bool has_type_param_bounds () const { return !type_param_bounds.empty (); } TraitItemType (Identifier name, + std::vector> generic_params, std::vector> type_param_bounds, std::vector outer_attrs, Visibility vis, location_t locus) : TraitItem (vis, locus), outer_attrs (std::move (outer_attrs)), - name (std::move (name)), type_param_bounds (std::move (type_param_bounds)) + name (std::move (name)), generic_params (std::move (generic_params)), + type_param_bounds (std::move (type_param_bounds)) {} // Copy constructor with vector clone @@ -2749,6 +2756,9 @@ class TraitItemType : public TraitItem name (other.name) { node_id = other.node_id; + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); 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 ()); @@ -2763,6 +2773,9 @@ class TraitItemType : public TraitItem locus = other.locus; node_id = other.node_id; + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); 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 ()); @@ -2786,7 +2799,15 @@ class TraitItemType : public TraitItem std::vector &get_outer_attrs () { return outer_attrs; } const std::vector &get_outer_attrs () const { return outer_attrs; } - // TODO: mutable getter seems kinda dodgy + std::vector> &get_generic_params () + { + return generic_params; + } + const std::vector> &get_generic_params () const + { + return generic_params; + } + std::vector> &get_type_param_bounds () { return type_param_bounds; diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index 014963fb520b..38a34748130e 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -177,7 +177,6 @@ class ImplTraitType : public Type void accept_vis (ASTVisitor &vis) override; - // TODO: mutable getter seems kinda dodgy std::vector > &get_type_param_bounds () { return type_param_bounds; @@ -250,7 +249,6 @@ class TraitObjectType : public Type bool is_dyn () const { return has_dyn; } - // TODO: mutable getter seems kinda dodgy std::vector > &get_type_param_bounds () { return type_param_bounds; @@ -463,7 +461,6 @@ class TupleType : public TypeNoBounds void accept_vis (ASTVisitor &vis) override; - // TODO: mutable getter seems kinda dodgy std::vector > &get_elems () { return elems; } const std::vector > &get_elems () const { diff --git a/gcc/rust/hir/rust-ast-lower-implitem.cc b/gcc/rust/hir/rust-ast-lower-implitem.cc index 8fd9d167cea3..87f1e015321e 100644 --- a/gcc/rust/hir/rust-ast-lower-implitem.cc +++ b/gcc/rust/hir/rust-ast-lower-implitem.cc @@ -55,11 +55,11 @@ ASTLowerImplItem::translate (AST::AssociatedItem &item, HirId parent_impl_id) void ASTLowerImplItem::visit (AST::TypeAlias &alias) { - std::vector > where_clause_items; + std::vector> where_clause_items; HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = translate_visibility (alias.get_visibility ()); - std::vector > generic_params; + std::vector> generic_params; if (alias.has_generics ()) generic_params = lower_generic_params (alias.get_generic_params ()); @@ -110,7 +110,7 @@ void ASTLowerImplItem::visit (AST::Function &function) { // ignore for now and leave empty - std::vector > where_clause_items; + std::vector> where_clause_items; for (auto &item : function.get_where_clause ().get_items ()) { HIR::WhereClauseItem *i @@ -124,7 +124,7 @@ ASTLowerImplItem::visit (AST::Function &function) HIR::Visibility vis = translate_visibility (function.get_visibility ()); // need - std::vector > generic_params; + std::vector> generic_params; if (function.has_generics ()) { generic_params = lower_generic_params (function.get_generic_params ()); @@ -233,12 +233,12 @@ ASTLowerTraitItem::translate (AST::AssociatedItem &item) void ASTLowerTraitItem::visit (AST::Function &func) { - std::vector > where_clause_items; + std::vector> where_clause_items; HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::FunctionQualifiers qualifiers = lower_qualifiers (func.get_qualifiers ()); - std::vector > generic_params; + std::vector> generic_params; if (func.has_generics ()) generic_params = lower_generic_params (func.get_generic_params ()); @@ -342,7 +342,24 @@ ASTLowerTraitItem::visit (AST::ConstantItem &constant) void ASTLowerTraitItem::visit (AST::TraitItemType &type) { - std::vector > type_param_bounds; + // Lower generic parameters (for GATs) + std::vector> generic_params; + for (auto ¶m : type.get_generic_params ()) + { + auto lowered_param = ASTLowerGenericParam::translate (*param.get ()); + generic_params.push_back ( + std::unique_ptr (lowered_param)); + } + + // Lower type parameter bounds + std::vector> type_param_bounds; + for (auto &bound : type.get_type_param_bounds ()) + { + auto lowered_bound = lower_bound (*bound.get ()); + type_param_bounds.push_back ( + std::unique_ptr (lowered_bound)); + } + auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), mappings.get_next_hir_id (crate_num), @@ -350,6 +367,7 @@ ASTLowerTraitItem::visit (AST::TraitItemType &type) HIR::TraitItemType *trait_item = new HIR::TraitItemType (mapping, type.get_identifier (), + std::move (generic_params), std::move (type_param_bounds), type.get_outer_attrs (), type.get_locus ()); translated = trait_item; diff --git a/gcc/rust/hir/tree/rust-hir-item.cc b/gcc/rust/hir/tree/rust-hir-item.cc index 1406e7aeb515..268b09b1ecaf 100644 --- a/gcc/rust/hir/tree/rust-hir-item.cc +++ b/gcc/rust/hir/tree/rust-hir-item.cc @@ -716,17 +716,21 @@ TraitItemConst::operator= (TraitItemConst const &other) TraitItemType::TraitItemType ( Analysis::NodeMapping mappings, Identifier name, + std::vector> generic_params, std::vector> type_param_bounds, AST::AttrVec outer_attrs, location_t locus) : TraitItem (mappings), outer_attrs (std::move (outer_attrs)), - name (std::move (name)), type_param_bounds (std::move (type_param_bounds)), - locus (locus) + name (std::move (name)), generic_params (std::move (generic_params)), + type_param_bounds (std::move (type_param_bounds)), locus (locus) {} TraitItemType::TraitItemType (TraitItemType const &other) : TraitItem (other.mappings), outer_attrs (other.outer_attrs), name (other.name), locus (other.locus) { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); 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 ()); @@ -741,6 +745,9 @@ TraitItemType::operator= (TraitItemType const &other) locus = other.locus; mappings = other.mappings; + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); 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 ()); diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index eb9cec741963..76294061d974 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -2121,15 +2121,20 @@ class TraitItemType : public TraitItem AST::AttrVec outer_attrs; Identifier name; + // Generic parameters for GATs (Generic Associated Types) + std::vector> generic_params; std::vector> type_param_bounds; // inlined form location_t locus; public: + bool has_generics () const { return !generic_params.empty (); } + // Returns whether trait item type has type param bounds. bool has_type_param_bounds () const { return !type_param_bounds.empty (); } TraitItemType (Analysis::NodeMapping mappings, Identifier name, + std::vector> generic_params, std::vector> type_param_bounds, AST::AttrVec outer_attrs, location_t locus); @@ -2152,6 +2157,15 @@ class TraitItemType : public TraitItem Identifier get_name () const { return name; } + std::vector> &get_generic_params () + { + return generic_params; + } + const std::vector> &get_generic_params () const + { + return generic_params; + } + std::vector> &get_type_param_bounds () { return type_param_bounds; diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc index 57f560b06d3e..614fec7076e1 100644 --- a/gcc/rust/hir/tree/rust-hir.cc +++ b/gcc/rust/hir/tree/rust-hir.cc @@ -3582,6 +3582,18 @@ TraitItemType::as_string () const str += "\ntype " + name.as_string (); + if (has_generics ()) + { + str += "<"; + for (size_t i = 0; i < generic_params.size (); i++) + { + if (i > 0) + str += ", "; + str += generic_params[i]->as_string (); + } + str += ">"; + } + str += "\n Type param bounds: "; if (!has_type_param_bounds ()) { diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 64554f5e9e49..0421d6cb80e5 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -5221,6 +5221,13 @@ Parser::parse_trait_type (AST::AttrVec outer_attrs, Identifier ident{ident_tok}; + // Parse optional generic parameters for GATs (Generic Associated Types) + std::vector> generic_params; + if (lexer.peek_token ()->get_id () == LEFT_ANGLE) + { + generic_params = parse_generic_params_in_angles (); + } + std::vector> bounds; // parse optional colon @@ -5241,8 +5248,9 @@ Parser::parse_trait_type (AST::AttrVec outer_attrs, } return std::unique_ptr ( - new AST::TraitItemType (std::move (ident), std::move (bounds), - std::move (outer_attrs), vis, locus)); + new AST::TraitItemType (std::move (ident), std::move (generic_params), + std::move (bounds), std::move (outer_attrs), vis, + locus)); } // Parses a constant trait item. diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc index 83adf2ea761b..8df8a18bddd0 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc @@ -519,6 +519,12 @@ TypeCheckImplItemWithTrait::visit (HIR::ConstantItem &constant) void TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type) { + auto binder_pin = context->push_lifetime_binder (); + + if (type.has_generics ()) + resolve_generic_params (HIR::Item::ItemKind::TypeAlias, type.get_locus (), + type.get_generic_params (), substitutions); + // normal resolution of the item TyTy::BaseType *lookup = TypeCheckImplItem::Resolve (parent, type, self, substitutions); diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 480e244fd38e..5386b72f602f 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -890,7 +890,7 @@ BaseType::is_concrete () const bool BaseType::has_substitutions_defined () const { - const TyTy::BaseType *x = destructure (); + const auto x = this; switch (x->get_kind ()) { case INFER: diff --git a/gcc/testsuite/rust/compile/gat1.rs b/gcc/testsuite/rust/compile/gat1.rs new file mode 100644 index 000000000000..032f64e080ac --- /dev/null +++ b/gcc/testsuite/rust/compile/gat1.rs @@ -0,0 +1,4 @@ +trait Foo { + type Bar; + type Baz<'a>; +} diff --git a/gcc/testsuite/rust/execute/torture/gat1.rs b/gcc/testsuite/rust/execute/torture/gat1.rs new file mode 100644 index 000000000000..8310a5883809 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/gat1.rs @@ -0,0 +1,18 @@ +#[lang = "sized"] +trait Sized {} + +pub struct MyBuf; + +trait Foo { + type Bar: Sized; +} + +impl Foo for MyBuf { + type Bar = T; +} + +type A = ::Bar; +fn main() -> i32 { + let a: A = 1; + a as i32 - 1 +}