gccrs: Add declarations for Rust HIR

This patch contains the declarations needed for our second intermediate
representation, which we will refer to as an HIR.

This gives the front-end a chance to desugar much of the AST, such as:
- Removing distinction between functions and methods
- Removing Macros
- Removing IdentifierExprs
- Removing duplicate attribute structures

	gcc/rust/
	* hir/tree/rust-hir-expr.h: New.
	* hir/tree/rust-hir-item.h: New.
	* hir/tree/rust-hir-path.h: New.
	* hir/tree/rust-hir-pattern.h: New.
	* hir/tree/rust-hir-stmt.h: New.
	* hir/tree/rust-hir-type.h: New.
This commit is contained in:
Philip Herron 2022-10-21 13:44:20 +02:00 committed by Arthur Cohen
parent 85a8fe00f8
commit 8ad1d56d68
6 changed files with 10903 additions and 0 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,273 @@
// Copyright (C) 2020-2022 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_HIR_STATEMENT_H
#define RUST_HIR_STATEMENT_H
#include "rust-hir.h"
#include "rust-hir-path.h"
#include "rust-hir-expr.h"
namespace Rust {
namespace HIR {
// Just a semi-colon, which apparently is a statement.
class EmptyStmt : public Stmt
{
Location locus;
public:
std::string as_string () const override { return std::string (1, ';'); }
EmptyStmt (Analysis::NodeMapping mappings, Location locus)
: Stmt (std::move (mappings)), locus (locus)
{}
Location get_locus () const override final { return locus; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRStmtVisitor &vis) override;
bool is_item () const override final { return false; }
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
EmptyStmt *clone_stmt_impl () const override { return new EmptyStmt (*this); }
};
/* Variable assignment let statement - type of "declaration statement" as it
* introduces new name into scope */
class LetStmt : public Stmt
{
// bool has_outer_attrs;
AST::AttrVec outer_attrs;
std::unique_ptr<Pattern> variables_pattern;
// bool has_type;
std::unique_ptr<Type> type;
// bool has_init_expr;
std::unique_ptr<Expr> init_expr;
Location locus;
public:
// Returns whether let statement has outer attributes.
bool has_outer_attrs () const { return !outer_attrs.empty (); }
// Returns whether let statement has a given return type.
bool has_type () const { return type != nullptr; }
// Returns whether let statement has an initialisation expression.
bool has_init_expr () const { return init_expr != nullptr; }
std::string as_string () const override;
LetStmt (Analysis::NodeMapping mappings,
std::unique_ptr<Pattern> variables_pattern,
std::unique_ptr<Expr> init_expr, std::unique_ptr<Type> type,
AST::AttrVec outer_attrs, Location locus)
: Stmt (std::move (mappings)), outer_attrs (std::move (outer_attrs)),
variables_pattern (std::move (variables_pattern)),
type (std::move (type)), init_expr (std::move (init_expr)), locus (locus)
{}
// Copy constructor with clone
LetStmt (LetStmt const &other)
: Stmt (other.mappings), outer_attrs (other.outer_attrs),
locus (other.locus)
{
// guard to prevent null dereference (only required if error state)
if (other.variables_pattern != nullptr)
variables_pattern = other.variables_pattern->clone_pattern ();
// guard to prevent null dereference (always required)
if (other.init_expr != nullptr)
init_expr = other.init_expr->clone_expr ();
if (other.type != nullptr)
type = other.type->clone_type ();
}
// Overloaded assignment operator to clone
LetStmt &operator= (LetStmt const &other)
{
outer_attrs = other.outer_attrs;
locus = other.locus;
// guard to prevent null dereference (only required if error state)
if (other.variables_pattern != nullptr)
variables_pattern = other.variables_pattern->clone_pattern ();
else
variables_pattern = nullptr;
// guard to prevent null dereference (always required)
if (other.init_expr != nullptr)
init_expr = other.init_expr->clone_expr ();
else
init_expr = nullptr;
if (other.type != nullptr)
type = other.type->clone_type ();
else
type = nullptr;
return *this;
}
// move constructors
LetStmt (LetStmt &&other) = default;
LetStmt &operator= (LetStmt &&other) = default;
Location get_locus () const override final { return locus; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRStmtVisitor &vis) override;
HIR::Type *get_type () { return type.get (); }
HIR::Expr *get_init_expr () { return init_expr.get (); }
HIR::Pattern *get_pattern () { return variables_pattern.get (); }
bool is_item () const override final { return false; }
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
LetStmt *clone_stmt_impl () const override { return new LetStmt (*this); }
};
/* Abstract base class for expression statements (statements containing an
* expression) */
class ExprStmt : public Stmt
{
// TODO: add any useful virtual functions
Location locus;
public:
Location get_locus () const override final { return locus; }
bool is_item () const override final { return false; }
protected:
ExprStmt (Analysis::NodeMapping mappings, Location locus)
: Stmt (std::move (mappings)), locus (locus)
{}
};
/* Statement containing an expression without a block (or, due to technical
* difficulties, can only be guaranteed to hold an expression). */
class ExprStmtWithoutBlock : public ExprStmt
{
std::unique_ptr<Expr> expr;
public:
std::string as_string () const override;
ExprStmtWithoutBlock (Analysis::NodeMapping mappings,
std::unique_ptr<Expr> expr, Location locus)
: ExprStmt (std::move (mappings), locus), expr (std::move (expr))
{}
// Copy constructor with clone
ExprStmtWithoutBlock (ExprStmtWithoutBlock const &other)
: ExprStmt (other), expr (other.expr->clone_expr ())
{}
// Overloaded assignment operator to clone
ExprStmtWithoutBlock &operator= (ExprStmtWithoutBlock const &other)
{
ExprStmt::operator= (other);
expr = other.expr->clone_expr ();
return *this;
}
// move constructors
ExprStmtWithoutBlock (ExprStmtWithoutBlock &&other) = default;
ExprStmtWithoutBlock &operator= (ExprStmtWithoutBlock &&other) = default;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRStmtVisitor &vis) override;
Expr *get_expr () { return expr.get (); }
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
ExprStmtWithoutBlock *clone_stmt_impl () const override
{
return new ExprStmtWithoutBlock (*this);
}
};
// Statement containing an expression with a block
class ExprStmtWithBlock : public ExprStmt
{
std::unique_ptr<ExprWithBlock> expr;
bool must_be_unit;
public:
std::string as_string () const override;
ExprStmtWithBlock (Analysis::NodeMapping mappings,
std::unique_ptr<ExprWithBlock> expr, Location locus,
bool must_be_unit)
: ExprStmt (std::move (mappings), locus), expr (std::move (expr)),
must_be_unit (must_be_unit)
{}
// Copy constructor with clone
ExprStmtWithBlock (ExprStmtWithBlock const &other)
: ExprStmt (other), expr (other.expr->clone_expr_with_block ())
{}
// Overloaded assignment operator to clone
ExprStmtWithBlock &operator= (ExprStmtWithBlock const &other)
{
ExprStmt::operator= (other);
expr = other.expr->clone_expr_with_block ();
return *this;
}
// move constructors
ExprStmtWithBlock (ExprStmtWithBlock &&other) = default;
ExprStmtWithBlock &operator= (ExprStmtWithBlock &&other) = default;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRStmtVisitor &vis) override;
ExprWithBlock *get_expr () { return expr.get (); }
bool is_unit_check_needed () const override { return must_be_unit; }
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
ExprStmtWithBlock *clone_stmt_impl () const override
{
return new ExprStmtWithBlock (*this);
}
};
} // namespace HIR
} // namespace Rust
#endif

View File

@ -0,0 +1,860 @@
// Copyright (C) 2020-2022 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_HIR_TYPE_H
#define RUST_HIR_TYPE_H
#include "rust-common.h"
#include "rust-hir.h"
#include "rust-hir-path.h"
namespace Rust {
namespace HIR {
// definitions moved to rust-ast.h
class TypeParamBound;
class Lifetime;
// A trait bound
class TraitBound : public TypeParamBound
{
bool in_parens;
bool opening_question_mark;
std::vector<LifetimeParam> for_lifetimes;
TypePath type_path;
Location locus;
Analysis::NodeMapping mappings;
public:
// Returns whether trait bound has "for" lifetimes
bool has_for_lifetimes () const { return !for_lifetimes.empty (); }
TraitBound (Analysis::NodeMapping mapping, TypePath type_path, Location locus,
bool in_parens = false, bool opening_question_mark = false,
std::vector<LifetimeParam> for_lifetimes
= std::vector<LifetimeParam> ())
: in_parens (in_parens), opening_question_mark (opening_question_mark),
for_lifetimes (std::move (for_lifetimes)),
type_path (std::move (type_path)), locus (locus), mappings (mapping)
{}
std::string as_string () const override;
Location get_locus () const override final { return locus; }
void accept_vis (HIRFullVisitor &vis) override;
Analysis::NodeMapping get_mappings () const override final
{
return mappings;
}
BoundType get_bound_type () const final override { return TRAITBOUND; }
TypePath &get_path () { return type_path; }
const TypePath &get_path () const { return type_path; }
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
TraitBound *clone_type_param_bound_impl () const override
{
return new TraitBound (*this);
}
};
// definition moved to rust-ast.h
class TypeNoBounds;
// An impl trait? Poor reference material here.
class ImplTraitType : public Type
{
// TypeParamBounds type_param_bounds;
// inlined form
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
ImplTraitType *clone_type_impl () const override
{
return new ImplTraitType (*this);
}
public:
ImplTraitType (Analysis::NodeMapping mappings,
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
Location locus)
: Type (mappings, locus), type_param_bounds (std::move (type_param_bounds))
{}
// copy constructor with vector clone
ImplTraitType (ImplTraitType const &other)
: Type (other.mappings, other.locus)
{
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 ());
}
// overloaded assignment operator to clone
ImplTraitType &operator= (ImplTraitType const &other)
{
locus = other.locus;
mappings = other.mappings;
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 ());
return *this;
}
// move constructors
ImplTraitType (ImplTraitType &&other) = default;
ImplTraitType &operator= (ImplTraitType &&other) = default;
std::string as_string () const override;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRTypeVisitor &vis) override;
};
// An opaque value of another type that implements a set of traits
class TraitObjectType : public Type
{
bool has_dyn;
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
TraitObjectType *clone_type_impl () const override
{
return new TraitObjectType (*this);
}
public:
TraitObjectType (
Analysis::NodeMapping mappings,
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
Location locus, bool is_dyn_dispatch)
: Type (mappings, locus), has_dyn (is_dyn_dispatch),
type_param_bounds (std::move (type_param_bounds))
{}
// copy constructor with vector clone
TraitObjectType (TraitObjectType const &other)
: Type (other.mappings, other.locus), has_dyn (other.has_dyn)
{
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 ());
}
// overloaded assignment operator to clone
TraitObjectType &operator= (TraitObjectType const &other)
{
mappings = other.mappings;
has_dyn = other.has_dyn;
locus = other.locus;
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 ());
return *this;
}
// move constructors
TraitObjectType (TraitObjectType &&other) = default;
TraitObjectType &operator= (TraitObjectType &&other) = default;
std::string as_string () const override;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRTypeVisitor &vis) override;
std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
{
return type_param_bounds;
}
const std::vector<std::unique_ptr<TypeParamBound>> &
get_type_param_bounds () const
{
return type_param_bounds;
}
};
// A type with parentheses around it, used to avoid ambiguity.
class ParenthesisedType : public TypeNoBounds
{
std::unique_ptr<Type> type_in_parens;
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
ParenthesisedType *clone_type_impl () const override
{
return new ParenthesisedType (*this);
}
/* Use covariance to implement clone function as returning this object rather
* than base */
ParenthesisedType *clone_type_no_bounds_impl () const override
{
return new ParenthesisedType (*this);
}
public:
// Constructor uses Type pointer for polymorphism
ParenthesisedType (Analysis::NodeMapping mappings,
std::unique_ptr<Type> type_inside_parens, Location locus)
: TypeNoBounds (mappings, locus),
type_in_parens (std::move (type_inside_parens))
{}
/* Copy constructor uses custom deep copy method for type to preserve
* polymorphism */
ParenthesisedType (ParenthesisedType const &other)
: TypeNoBounds (other.mappings, other.locus),
type_in_parens (other.type_in_parens->clone_type ())
{}
// overload assignment operator to use custom clone method
ParenthesisedType &operator= (ParenthesisedType const &other)
{
mappings = other.mappings;
type_in_parens = other.type_in_parens->clone_type ();
locus = other.locus;
return *this;
}
// default move semantics
ParenthesisedType (ParenthesisedType &&other) = default;
ParenthesisedType &operator= (ParenthesisedType &&other) = default;
std::string as_string () const override
{
return "(" + type_in_parens->as_string () + ")";
}
// Creates a trait bound (clone of this one's trait bound) - HACK
TraitBound *to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const override
{
/* NOTE: obviously it is unknown whether the internal type is a trait bound
* due to polymorphism, so just let the internal type handle it. As
* parenthesised type, it must be in parentheses. */
return type_in_parens->to_trait_bound (true);
}
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRTypeVisitor &vis) override;
};
// Impl trait with a single bound? Poor reference material here.
class ImplTraitTypeOneBound : public TypeNoBounds
{
TraitBound trait_bound;
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
ImplTraitTypeOneBound *clone_type_impl () const override
{
return new ImplTraitTypeOneBound (*this);
}
/* Use covariance to implement clone function as returning this object rather
* than base */
ImplTraitTypeOneBound *clone_type_no_bounds_impl () const override
{
return new ImplTraitTypeOneBound (*this);
}
public:
ImplTraitTypeOneBound (Analysis::NodeMapping mappings, TraitBound trait_bound,
Location locus)
: TypeNoBounds (mappings, locus), trait_bound (std::move (trait_bound))
{}
std::string as_string () const override;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRTypeVisitor &vis) override;
};
class TypePath; // definition moved to "rust-path.h"
/* A type consisting of the "product" of others (the tuple's elements) in a
* specific order */
class TupleType : public TypeNoBounds
{
std::vector<std::unique_ptr<Type>> elems;
public:
// Returns whether the tuple type is the unit type, i.e. has no elements.
bool is_unit_type () const { return elems.empty (); }
TupleType (Analysis::NodeMapping mappings,
std::vector<std::unique_ptr<Type>> elems, Location locus)
: TypeNoBounds (mappings, locus), elems (std::move (elems))
{}
// copy constructor with vector clone
TupleType (TupleType const &other)
: TypeNoBounds (other.mappings, other.locus)
{
mappings = other.mappings;
elems.reserve (other.elems.size ());
for (const auto &e : other.elems)
elems.push_back (e->clone_type ());
}
// overloaded assignment operator to clone
TupleType &operator= (TupleType const &other)
{
locus = other.locus;
elems.reserve (other.elems.size ());
for (const auto &e : other.elems)
elems.push_back (e->clone_type ());
return *this;
}
// move constructors
TupleType (TupleType &&other) = default;
TupleType &operator= (TupleType &&other) = default;
std::string as_string () const override;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRTypeVisitor &vis) override;
std::vector<std::unique_ptr<Type>> &get_elems () { return elems; }
const std::vector<std::unique_ptr<Type>> &get_elems () const { return elems; }
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
TupleType *clone_type_impl () const override { return new TupleType (*this); }
/* Use covariance to implement clone function as returning this object rather
* than base */
TupleType *clone_type_no_bounds_impl () const override
{
return new TupleType (*this);
}
};
/* A type with no values, representing the result of computations that never
* complete. Expressions of NeverType can be coerced into any other types.
* Represented as "!". */
class NeverType : public TypeNoBounds
{
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
NeverType *clone_type_impl () const override { return new NeverType (*this); }
/* Use covariance to implement clone function as returning this object rather
* than base */
NeverType *clone_type_no_bounds_impl () const override
{
return new NeverType (*this);
}
public:
NeverType (Analysis::NodeMapping mappings, Location locus)
: TypeNoBounds (mappings, locus)
{}
std::string as_string () const override { return "! (never type)"; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRTypeVisitor &vis) override;
};
// A type consisting of a pointer without safety or liveness guarantees
class RawPointerType : public TypeNoBounds
{
private:
Mutability mut;
std::unique_ptr<Type> type;
public:
// Constructor requires pointer for polymorphism reasons
RawPointerType (Analysis::NodeMapping mappings, Mutability mut,
std::unique_ptr<Type> type, Location locus)
: TypeNoBounds (mappings, locus), mut (mut), type (std::move (type))
{}
// Copy constructor calls custom polymorphic clone function
RawPointerType (RawPointerType const &other)
: TypeNoBounds (other.mappings, other.locus), mut (other.mut),
type (other.type->clone_type ())
{}
// overload assignment operator to use custom clone method
RawPointerType &operator= (RawPointerType const &other)
{
mappings = other.mappings;
mut = other.mut;
type = other.type->clone_type ();
locus = other.locus;
return *this;
}
// default move semantics
RawPointerType (RawPointerType &&other) = default;
RawPointerType &operator= (RawPointerType &&other) = default;
std::string as_string () const override;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRTypeVisitor &vis) override;
std::unique_ptr<Type> &get_type () { return type; }
Mutability get_mut () const { return mut; }
bool is_mut () const { return mut == Mutability::Mut; }
bool is_const () const { return mut == Mutability::Imm; }
std::unique_ptr<Type> &get_base_type () { return type; }
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
RawPointerType *clone_type_impl () const override
{
return new RawPointerType (*this);
}
/* Use covariance to implement clone function as returning this object rather
* than base */
RawPointerType *clone_type_no_bounds_impl () const override
{
return new RawPointerType (*this);
}
};
// A type pointing to memory owned by another value
class ReferenceType : public TypeNoBounds
{
// bool has_lifetime; // TODO: handle in lifetime or something?
Lifetime lifetime;
Mutability mut;
std::unique_ptr<Type> type;
public:
// Returns whether the reference is mutable or immutable.
bool is_mut () const { return mut == Mutability::Mut; }
// Returns whether the reference has a lifetime.
bool has_lifetime () const { return !lifetime.is_error (); }
// Constructor
ReferenceType (Analysis::NodeMapping mappings, Mutability mut,
std::unique_ptr<Type> type_no_bounds, Location locus,
Lifetime lifetime)
: TypeNoBounds (mappings, locus), lifetime (std::move (lifetime)),
mut (mut), type (std::move (type_no_bounds))
{}
// Copy constructor with custom clone method
ReferenceType (ReferenceType const &other)
: TypeNoBounds (other.mappings, other.locus), lifetime (other.lifetime),
mut (other.mut), type (other.type->clone_type ())
{}
// Operator overload assignment operator to custom clone the unique pointer
ReferenceType &operator= (ReferenceType const &other)
{
mappings = other.mappings;
lifetime = other.lifetime;
mut = other.mut;
type = other.type->clone_type ();
locus = other.locus;
return *this;
}
// move constructors
ReferenceType (ReferenceType &&other) = default;
ReferenceType &operator= (ReferenceType &&other) = default;
std::string as_string () const override;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRTypeVisitor &vis) override;
Lifetime &get_lifetime () { return lifetime; }
Mutability get_mut () const { return mut; }
std::unique_ptr<Type> &get_base_type () { return type; }
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
ReferenceType *clone_type_impl () const override
{
return new ReferenceType (*this);
}
/* Use covariance to implement clone function as returning this object rather
* than base */
ReferenceType *clone_type_no_bounds_impl () const override
{
return new ReferenceType (*this);
}
};
// A fixed-size sequence of elements of a specified type
class ArrayType : public TypeNoBounds
{
std::unique_ptr<Type> elem_type;
std::unique_ptr<Expr> size;
public:
// Constructor requires pointers for polymorphism
ArrayType (Analysis::NodeMapping mappings, std::unique_ptr<Type> type,
std::unique_ptr<Expr> array_size, Location locus)
: TypeNoBounds (mappings, locus), elem_type (std::move (type)),
size (std::move (array_size))
{}
// Copy constructor requires deep copies of both unique pointers
ArrayType (ArrayType const &other)
: TypeNoBounds (other.mappings, other.locus),
elem_type (other.elem_type->clone_type ()),
size (other.size->clone_expr ())
{}
// Overload assignment operator to deep copy pointers
ArrayType &operator= (ArrayType const &other)
{
mappings = other.mappings;
elem_type = other.elem_type->clone_type ();
size = other.size->clone_expr ();
locus = other.locus;
return *this;
}
// move constructors
ArrayType (ArrayType &&other) = default;
ArrayType &operator= (ArrayType &&other) = default;
std::string as_string () const override;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRTypeVisitor &vis) override;
Type *get_element_type () { return elem_type.get (); }
Expr *get_size_expr () { return size.get (); }
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
ArrayType *clone_type_impl () const override { return new ArrayType (*this); }
/* Use covariance to implement clone function as returning this object rather
* than base */
ArrayType *clone_type_no_bounds_impl () const override
{
return new ArrayType (*this);
}
};
/* A dynamically-sized type representing a "view" into a sequence of elements of
* a type */
class SliceType : public TypeNoBounds
{
std::unique_ptr<Type> elem_type;
public:
// Constructor requires pointer for polymorphism
SliceType (Analysis::NodeMapping mappings, std::unique_ptr<Type> type,
Location locus)
: TypeNoBounds (mappings, locus), elem_type (std::move (type))
{}
// Copy constructor requires deep copy of Type smart pointer
SliceType (SliceType const &other)
: TypeNoBounds (other.mappings, other.locus),
elem_type (other.elem_type->clone_type ())
{}
// Overload assignment operator to deep copy
SliceType &operator= (SliceType const &other)
{
mappings = other.mappings;
elem_type = other.elem_type->clone_type ();
locus = other.locus;
return *this;
}
// move constructors
SliceType (SliceType &&other) = default;
SliceType &operator= (SliceType &&other) = default;
std::string as_string () const override;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRTypeVisitor &vis) override;
std::unique_ptr<Type> &get_element_type () { return elem_type; }
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
SliceType *clone_type_impl () const override { return new SliceType (*this); }
/* Use covariance to implement clone function as returning this object rather
* than base */
SliceType *clone_type_no_bounds_impl () const override
{
return new SliceType (*this);
}
};
/* Type used in generic arguments to explicitly request type inference (wildcard
* pattern) */
class InferredType : public TypeNoBounds
{
// e.g. Vec<_> = whatever
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
InferredType *clone_type_impl () const override
{
return new InferredType (*this);
}
/* Use covariance to implement clone function as returning this object rather
* than base */
InferredType *clone_type_no_bounds_impl () const override
{
return new InferredType (*this);
}
public:
InferredType (Analysis::NodeMapping mappings, Location locus)
: TypeNoBounds (mappings, locus)
{}
std::string as_string () const override;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRTypeVisitor &vis) override;
};
class QualifiedPathInType; // definition moved to "rust-path.h"
// A possibly named param used in a BaseFunctionType
struct MaybeNamedParam
{
public:
enum ParamKind
{
UNNAMED,
IDENTIFIER,
WILDCARD
};
private:
std::unique_ptr<Type> param_type;
ParamKind param_kind;
Identifier name; // technically, can be an identifier or '_'
Location locus;
public:
MaybeNamedParam (Identifier name, ParamKind param_kind,
std::unique_ptr<Type> param_type, Location locus)
: param_type (std::move (param_type)), param_kind (param_kind),
name (std::move (name)), locus (locus)
{}
// Copy constructor with clone
MaybeNamedParam (MaybeNamedParam const &other)
: param_type (other.param_type->clone_type ()),
param_kind (other.param_kind), name (other.name), locus (other.locus)
{}
~MaybeNamedParam () = default;
// Overloaded assignment operator with clone
MaybeNamedParam &operator= (MaybeNamedParam const &other)
{
name = other.name;
param_kind = other.param_kind;
param_type = other.param_type->clone_type ();
locus = other.locus;
return *this;
}
// move constructors
MaybeNamedParam (MaybeNamedParam &&other) = default;
MaybeNamedParam &operator= (MaybeNamedParam &&other) = default;
std::string as_string () const;
// Returns whether the param is in an error state.
bool is_error () const { return param_type == nullptr; }
// Creates an error state param.
static MaybeNamedParam create_error ()
{
return MaybeNamedParam ("", UNNAMED, nullptr, Location ());
}
Location get_locus () const { return locus; }
std::unique_ptr<Type> &get_type ()
{
rust_assert (param_type != nullptr);
return param_type;
}
ParamKind get_param_kind () const { return param_kind; }
Identifier get_name () const { return name; }
};
/* A function pointer type - can be created via coercion from function items and
* non- capturing closures. */
class BareFunctionType : public TypeNoBounds
{
// bool has_for_lifetimes;
// ForLifetimes for_lifetimes;
std::vector<LifetimeParam> for_lifetimes; // inlined version
FunctionQualifiers function_qualifiers;
std::vector<MaybeNamedParam> params;
bool is_variadic;
std::unique_ptr<Type> return_type; // inlined version
public:
// Whether a return type is defined with the function.
bool has_return_type () const { return return_type != nullptr; }
// Whether the function has ForLifetimes.
bool has_for_lifetimes () const { return !for_lifetimes.empty (); }
BareFunctionType (Analysis::NodeMapping mappings,
std::vector<LifetimeParam> lifetime_params,
FunctionQualifiers qualifiers,
std::vector<MaybeNamedParam> named_params, bool is_variadic,
std::unique_ptr<Type> type, Location locus)
: TypeNoBounds (mappings, locus),
for_lifetimes (std::move (lifetime_params)),
function_qualifiers (std::move (qualifiers)),
params (std::move (named_params)), is_variadic (is_variadic),
return_type (std::move (type))
{}
// Copy constructor with clone
BareFunctionType (BareFunctionType const &other)
: TypeNoBounds (other.mappings, other.locus),
for_lifetimes (other.for_lifetimes),
function_qualifiers (other.function_qualifiers), params (other.params),
is_variadic (other.is_variadic),
return_type (other.return_type->clone_type ())
{}
// Overload assignment operator to deep copy
BareFunctionType &operator= (BareFunctionType const &other)
{
mappings = other.mappings;
for_lifetimes = other.for_lifetimes;
function_qualifiers = other.function_qualifiers;
params = other.params;
is_variadic = other.is_variadic;
return_type = other.return_type->clone_type ();
locus = other.locus;
return *this;
}
// move constructors
BareFunctionType (BareFunctionType &&other) = default;
BareFunctionType &operator= (BareFunctionType &&other) = default;
std::string as_string () const override;
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRTypeVisitor &vis) override;
std::vector<MaybeNamedParam> &get_function_params () { return params; }
const std::vector<MaybeNamedParam> &get_function_params () const
{
return params;
}
// TODO: would a "vis_type" be better?
std::unique_ptr<Type> &get_return_type ()
{
rust_assert (has_return_type ());
return return_type;
}
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
BareFunctionType *clone_type_impl () const override
{
return new BareFunctionType (*this);
}
/* Use covariance to implement clone function as returning this object rather
* than base */
BareFunctionType *clone_type_no_bounds_impl () const override
{
return new BareFunctionType (*this);
}
};
/* TODO: possible types
* struct type?
* "enum" (tagged union) type?
* C-like union type?
* function item type?
* closure expression types?
* primitive types (bool, int, float, char, str (the slice))
* Although supposedly TypePaths are used to reference these types (including
* primitives) */
/* FIXME: Incomplete spec references:
* anonymous type parameters, aka "impl Trait in argument position" - impl then
* trait bounds abstract return types, aka "impl Trait in return position" -
* impl then trait bounds */
} // namespace HIR
} // namespace Rust
#endif