Skip to content

Commit

Permalink
rust: Add support for Clone and Copy derive on generic types
Browse files Browse the repository at this point in the history
When we generate derivations for Copy and Clone we need to make sure
the associated impl block sets up the generic parameters and arguments
correctly. This patch introduces the framework to copy chunks of the AST
because we need to make sure these new AST nodes have their own associated
id, calling clone on the nodes will just confuse name-resolution and
subsequent mappings.

Fixes #3139

gcc/rust/ChangeLog:

	* Make-lang.in: new objects
	* ast/rust-ast-builder.cc (Builder::generic_type_path_segment): new helper
	(Builder::single_generic_type_path): likewise
	(Builder::new_type): likewise
	(Builder::new_lifetime_param): likewise
	(Builder::new_type_param): likewise
	(Builder::new_lifetime): likewise
	(Builder::new_generic_args): likewise
	* ast/rust-ast-builder.h: new helper decls
	* ast/rust-ast.h: new const getters
	* ast/rust-path.h: likewise
	* ast/rust-type.h: likewise
	* expand/rust-derive-clone.cc (DeriveClone::clone_impl): take the types generics
	(DeriveClone::visit_tuple): likewise
	(DeriveClone::visit_struct): likewise
	(DeriveClone::visit_union): likewise
	* expand/rust-derive-clone.h: update header
	* expand/rust-derive-copy.cc (DeriveCopy::copy_impl): similarly take type generics
	(DeriveCopy::visit_struct): likewise
	(DeriveCopy::visit_tuple): likewise
	(DeriveCopy::visit_enum): likewise
	(DeriveCopy::visit_union): likewise
	* expand/rust-derive-copy.h: likewse
	* ast/rust-ast-builder-type.cc: New file.
	* ast/rust-ast-builder-type.h: New file.

gcc/testsuite/ChangeLog:

	* rust/compile/issue-3139-1.rs: New test.
	* rust/compile/issue-3139-2.rs: New test.
	* rust/compile/issue-3139-3.rs: New test.
	* rust/compile/nr2/exclude: these all break nr2
  • Loading branch information
philberty committed Sep 27, 2024
1 parent 423122c commit c6a479f
Show file tree
Hide file tree
Showing 16 changed files with 783 additions and 22 deletions.
1 change: 1 addition & 0 deletions gcc/rust/Make-lang.in
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ GRS_OBJS = \
rust/rust-cfg-strip.o \
rust/rust-expand-visitor.o \
rust/rust-ast-builder.o \
rust/rust-ast-builder-type.o \
rust/rust-derive.o \
rust/rust-derive-clone.o \
rust/rust-derive-copy.o \
Expand Down
164 changes: 164 additions & 0 deletions gcc/rust/ast/rust-ast-builder-type.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// Copyright (C) 2020-2024 Free Software Foundation, Inc.

// This file is part of GCC.

// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.

// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.

// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.

#include "rust-ast-builder-type.h"
#include "rust-ast-builder.h"
#include "rust-ast-full.h"
#include "rust-common.h"
#include "rust-make-unique.h"

namespace Rust {
namespace AST {

ASTTypeBuilder::ASTTypeBuilder () : translated (nullptr) {}

Type *
ASTTypeBuilder::build (Type &type)
{
ASTTypeBuilder builder;
type.accept_vis (builder);
rust_assert (builder.translated != nullptr);
return builder.translated;
}

void
ASTTypeBuilder::visit (BareFunctionType &fntype)
{
/* TODO */
}

void
ASTTypeBuilder::visit (TupleType &tuple)
{
std::vector<std::unique_ptr<Type> > elems;
for (auto &elem : tuple.get_elems ())
{
Type *t = ASTTypeBuilder::build (*elem.get ());
std::unique_ptr<Type> ty (t);
elems.push_back (std::move (ty));
}
translated = new TupleType (std::move (elems), tuple.get_locus ());
}

void
ASTTypeBuilder::visit (TypePath &path)
{
std::vector<std::unique_ptr<TypePathSegment> > segments;
for (auto &seg : path.get_segments ())
{
switch (seg->get_type ())
{
case TypePathSegment::REG: {
const TypePathSegment &segment
= (const TypePathSegment &) (*seg.get ());
TypePathSegment *s
= new TypePathSegment (segment.get_ident_segment (),
segment.get_separating_scope_resolution (),
segment.get_locus ());
std::unique_ptr<TypePathSegment> sg (s);
segments.push_back (std::move (sg));
}
break;

case TypePathSegment::GENERIC: {
TypePathSegmentGeneric &generic
= (TypePathSegmentGeneric &) (*seg.get ());

GenericArgs args
= Builder::new_generic_args (generic.get_generic_args ());
TypePathSegmentGeneric *s
= new TypePathSegmentGeneric (generic.get_ident_segment (), false,
std::move (args),
generic.get_locus ());
std::unique_ptr<TypePathSegment> sg (s);
segments.push_back (std::move (sg));
}
break;

case TypePathSegment::FUNCTION: {
rust_unreachable ();
// TODO
// const TypePathSegmentFunction &fn
// = (const TypePathSegmentFunction &) (*seg.get ());
}
break;
}
}

translated = new TypePath (std::move (segments), path.get_locus (),
path.has_opening_scope_resolution_op ());
}

void
ASTTypeBuilder::visit (QualifiedPathInType &path)
{
/* TODO */
}

void
ASTTypeBuilder::visit (ArrayType &type)
{
/* TODO */
}

void
ASTTypeBuilder::visit (ReferenceType &type)
{
/* TODO */
}

void
ASTTypeBuilder::visit (RawPointerType &type)
{
/* TODO */
}

void
ASTTypeBuilder::visit (SliceType &type)
{
Type *t = ASTTypeBuilder::build (type.get_elem_type ());
std::unique_ptr<Type> ty (t);
translated = new SliceType (std::move (ty), type.get_locus ());
}

void
ASTTypeBuilder::visit (InferredType &type)
{
translated = new InferredType (type.get_locus ());
}

void
ASTTypeBuilder::visit (NeverType &type)
{
translated = new NeverType (type.get_locus ());
}

void
ASTTypeBuilder::visit (TraitObjectTypeOneBound &type)
{
/* TODO */
}

void
ASTTypeBuilder::visit (TraitObjectType &type)
{
/* TODO */
}

} // namespace AST
} // namespace Rust
57 changes: 57 additions & 0 deletions gcc/rust/ast/rust-ast-builder-type.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (C) 2020-2024 Free Software Foundation, Inc.

// This file is part of GCC.

// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.

// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.

// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.

#ifndef RUST_AST_BUILDER_TYPE
#define RUST_AST_BUILDER_TYPE

#include "rust-ast-visitor.h"

namespace Rust {
namespace AST {

class ASTTypeBuilder : public DefaultASTVisitor
{
protected:
using DefaultASTVisitor::visit;

public:
static Type *build (Type &type);

void visit (BareFunctionType &fntype) override;
void visit (TupleType &tuple) override;
void visit (TypePath &path) override;
void visit (QualifiedPathInType &path) override;
void visit (ArrayType &type) override;
void visit (ReferenceType &type) override;
void visit (RawPointerType &type) override;
void visit (SliceType &type) override;
void visit (InferredType &type) override;
void visit (NeverType &type) override;
void visit (TraitObjectTypeOneBound &type) override;
void visit (TraitObjectType &type) override;

private:
ASTTypeBuilder ();

Type *translated;
};

} // namespace AST
} // namespace Rust

#endif // RUST_AST_BUILDER_TYPE
Loading

0 comments on commit c6a479f

Please sign in to comment.