This patch is the initial part in supporting generic associated types. In rust we have
trait item types that get implemented for example:
trait Foo<T> {
type Bar
}
impl<T> Foo for T {
type Bar = T
}
The trait position uses a Ty::Placeholder which is just a thing that gets set for
lazy evaluation to the impl type alias which is actually a Ty::Projection see:
0798add3d3c1bf4b20ecc1b4fa1047ba4ba19759
For more info the projection type needs to hold onto generics in order to properly
support generic types this GAT's support extends this all the way to the placeholder
which still needs to be done.
Fixes Rust-GCC#4276
gcc/rust/ChangeLog:
* ast/rust-ast.cc (TraitItemType::as_string): add generic params
* ast/rust-ast.h: remove old comment
* ast/rust-item.h: add generic params to associated type
* ast/rust-type.h: remove old comment
* hir/rust-ast-lower-implitem.cc (ASTLowerTraitItem::visit): hir lowering for gat's
* hir/tree/rust-hir-item.cc (TraitItemType::TraitItemType): gat's on TraitItemType
(TraitItemType::operator=): preserve generic params
* hir/tree/rust-hir-item.h: likewise
* hir/tree/rust-hir.cc (TraitItemType::as_string): likewise
* parse/rust-parse-impl.h (Parser::parse_trait_type): hit the < and parse params
* typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItemWithTrait::visit): typecheck
* typecheck/rust-tyty.cc (BaseType::has_substitutions_defined): dont destructure
gcc/testsuite/ChangeLog:
* rust/compile/gat1.rs: New test.
* rust/execute/torture/gat1.rs: New test.
Signed-off-by: Philip Herron <herron.philip@googlemail.com>
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 ())
{
{
parsed_items = std::move (new_items);
}
- // TODO: mutable getter seems kinda dodgy
std::vector<std::unique_ptr<MetaItemInner>> &get_meta_items ()
{
return parsed_items;
Identifier name;
+ // Generic parameters for GATs (Generic Associated Types)
+ std::vector<std::unique_ptr<GenericParam>> generic_params;
+
// bool has_type_param_bounds;
// TypeParamBounds type_param_bounds;
std::vector<std::unique_ptr<TypeParamBound>>
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<std::unique_ptr<GenericParam>> generic_params,
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
std::vector<Attribute> 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
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 ());
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 ());
std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
- // TODO: mutable getter seems kinda dodgy
+ std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
+ {
+ return generic_params;
+ }
+
std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
{
return type_param_bounds;
void accept_vis (ASTVisitor &vis) override;
- // TODO: mutable getter seems kinda dodgy
std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
{
return type_param_bounds;
bool is_dyn () const { return has_dyn; }
- // TODO: mutable getter seems kinda dodgy
std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
{
return type_param_bounds;
void accept_vis (ASTVisitor &vis) override;
- // TODO: mutable getter seems kinda dodgy
std::vector<std::unique_ptr<Type> > &get_elems () { return elems; }
const std::vector<std::unique_ptr<Type> > &get_elems () const
{
void
ASTLowerImplItem::visit (AST::TypeAlias &alias)
{
- std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
+ std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
HIR::WhereClause where_clause (std::move (where_clause_items));
HIR::Visibility vis = translate_visibility (alias.get_visibility ());
- std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
+ std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
if (alias.has_generics ())
generic_params = lower_generic_params (alias.get_generic_params ());
ASTLowerImplItem::visit (AST::Function &function)
{
// ignore for now and leave empty
- std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
+ std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
for (auto &item : function.get_where_clause ().get_items ())
{
HIR::WhereClauseItem *i
HIR::Visibility vis = translate_visibility (function.get_visibility ());
// need
- std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
+ std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
if (function.has_generics ())
{
generic_params = lower_generic_params (function.get_generic_params ());
void
ASTLowerTraitItem::visit (AST::Function &func)
{
- std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
+ std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
HIR::WhereClause where_clause (std::move (where_clause_items));
HIR::FunctionQualifiers qualifiers
= lower_qualifiers (func.get_qualifiers ());
- std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
+ std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
if (func.has_generics ())
generic_params = lower_generic_params (func.get_generic_params ());
void
ASTLowerTraitItem::visit (AST::TraitItemType &type)
{
- std::vector<std::unique_ptr<HIR::TypeParamBound> > type_param_bounds;
+ // Lower generic parameters (for GATs)
+ std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+ for (auto ¶m : type.get_generic_params ())
+ {
+ auto lowered_param = ASTLowerGenericParam::translate (*param.get ());
+ generic_params.push_back (
+ std::unique_ptr<HIR::GenericParam> (lowered_param));
+ }
+
+ // Lower type parameter bounds
+ std::vector<std::unique_ptr<HIR::TypeParamBound>> 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<HIR::TypeParamBound> (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),
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;
TraitItemType::TraitItemType (
Analysis::NodeMapping mappings, Identifier name,
+ std::vector<std::unique_ptr<GenericParam>> generic_params,
std::vector<std::unique_ptr<TypeParamBound>> 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 ());
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 ());
AST::AttrVec outer_attrs;
Identifier name;
+ // Generic parameters for GATs (Generic Associated Types)
+ std::vector<std::unique_ptr<GenericParam>> generic_params;
std::vector<std::unique_ptr<TypeParamBound>>
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<std::unique_ptr<GenericParam>> generic_params,
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
AST::AttrVec outer_attrs, location_t locus);
Identifier get_name () const { return name; }
+ std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
+ {
+ return generic_params;
+ }
+
std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
{
return type_param_bounds;
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 ())
{
Identifier ident{ident_tok};
+ // Parse optional generic parameters for GATs (Generic Associated Types)
+ std::vector<std::unique_ptr<AST::GenericParam>> generic_params;
+ if (lexer.peek_token ()->get_id () == LEFT_ANGLE)
+ {
+ generic_params = parse_generic_params_in_angles ();
+ }
+
std::vector<std::unique_ptr<AST::TypeParamBound>> bounds;
// parse optional colon
}
return std::unique_ptr<AST::TraitItemType> (
- 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.
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);
bool
BaseType::has_substitutions_defined () const
{
- const TyTy::BaseType *x = destructure ();
+ const auto x = this;
switch (x->get_kind ())
{
case INFER:
--- /dev/null
+trait Foo {
+ type Bar<T>;
+ type Baz<'a>;
+}
--- /dev/null
+#[lang = "sized"]
+trait Sized {}
+
+pub struct MyBuf;
+
+trait Foo {
+ type Bar<T>: Sized;
+}
+
+impl Foo for MyBuf {
+ type Bar<T> = T;
+}
+
+type A = <MyBuf as Foo>::Bar<u32>;
+fn main() -> i32 {
+ let a: A = 1;
+ a as i32 - 1
+}