blob: efe59bd6f79414fb9cc8449f0a83f9bd744e5b26 [file] [log] [blame]
// Copyright (C) 2020-2023 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_TYPE_H
#define RUST_AST_TYPE_H
#include "rust-ast.h"
#include "rust-path.h"
namespace Rust {
namespace AST {
// definitions moved to rust-ast.h
class TypeParamBound;
class Lifetime;
// A trait bound
class TraitBound : public TypeParamBound
{
bool in_parens;
bool opening_question_mark;
// bool has_for_lifetimes;
// LifetimeParams for_lifetimes;
std::vector<LifetimeParam> for_lifetimes; // inlined LifetimeParams
TypePath type_path;
Location locus;
public:
// Returns whether trait bound has "for" lifetimes
bool has_for_lifetimes () const { return !for_lifetimes.empty (); }
std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; }
TraitBound (TypePath type_path, Location locus, bool in_parens = false,
bool opening_question_mark = false,
std::vector<LifetimeParam> for_lifetimes
= std::vector<LifetimeParam> ())
: TypeParamBound (Analysis::Mappings::get ()->get_next_node_id ()),
in_parens (in_parens), opening_question_mark (opening_question_mark),
for_lifetimes (std::move (for_lifetimes)),
type_path (std::move (type_path)), locus (locus)
{}
TraitBound (NodeId id, TypePath type_path, Location locus,
bool in_parens = false, bool opening_question_mark = false,
std::vector<LifetimeParam> for_lifetimes
= std::vector<LifetimeParam> ())
: TypeParamBound (id), in_parens (in_parens),
opening_question_mark (opening_question_mark),
for_lifetimes (std::move (for_lifetimes)),
type_path (std::move (type_path)), locus (locus)
{}
std::string as_string () const override;
Location get_locus () const override final { return locus; }
void accept_vis (ASTVisitor &vis) override;
// TODO: this mutable getter seems kinda dodgy
TypePath &get_type_path () { return type_path; }
const TypePath &get_type_path () const { return type_path; }
bool is_in_parens () const { return in_parens; }
bool has_opening_question_mark () const { return opening_question_mark; }
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 (node_id, type_path, locus, in_parens,
opening_question_mark, for_lifetimes);
}
};
// 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;
Location locus;
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 (
std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds,
Location locus)
: type_param_bounds (std::move (type_param_bounds)), locus (locus)
{}
// copy constructor with vector clone
ImplTraitType (ImplTraitType const &other) : 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 ());
}
// overloaded assignment operator to clone
ImplTraitType &operator= (ImplTraitType const &other)
{
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
ImplTraitType (ImplTraitType &&other) = default;
ImplTraitType &operator= (ImplTraitType &&other) = default;
std::string as_string () const override;
Location get_locus () const override final { return locus; }
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;
}
const std::vector<std::unique_ptr<TypeParamBound> > &
get_type_param_bounds () const
{
return type_param_bounds;
}
};
// 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;
Location locus;
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 (
std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds,
Location locus, bool is_dyn_dispatch)
: has_dyn (is_dyn_dispatch),
type_param_bounds (std::move (type_param_bounds)), locus (locus)
{}
// copy constructor with vector clone
TraitObjectType (TraitObjectType const &other)
: 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 ());
}
// overloaded assignment operator to clone
TraitObjectType &operator= (TraitObjectType const &other)
{
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;
Location get_locus () const override final { return locus; }
void accept_vis (ASTVisitor &vis) override;
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;
}
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;
Location locus;
protected:
/* 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 (std::unique_ptr<Type> type_inside_parens, Location locus)
: type_in_parens (std::move (type_inside_parens)), locus (locus)
{}
/* Copy constructor uses custom deep copy method for type to preserve
* polymorphism */
ParenthesisedType (ParenthesisedType const &other)
: type_in_parens (other.type_in_parens->clone_type ()), locus (other.locus)
{}
// overload assignment operator to use custom clone method
ParenthesisedType &operator= (ParenthesisedType const &other)
{
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) 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);
}
Location get_locus () const override final { return locus; }
void accept_vis (ASTVisitor &vis) override;
// TODO: would a "vis_type" be better?
std::unique_ptr<Type> &get_type_in_parens ()
{
rust_assert (type_in_parens != nullptr);
return type_in_parens;
}
};
// Impl trait with a single bound? Poor reference material here.
class ImplTraitTypeOneBound : public TypeNoBounds
{
TraitBound trait_bound;
Location locus;
protected:
/* 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 (TraitBound trait_bound, Location locus)
: trait_bound (std::move (trait_bound)), locus (locus)
{}
std::string as_string () const override;
Location get_locus () const override final { return locus; }
void accept_vis (ASTVisitor &vis) override;
// TODO: would a "vis_type" be better?
TraitBound &get_trait_bound ()
{
// TODO: check to ensure invariants are met?
return trait_bound;
}
};
/* A trait object with a single trait bound. The "trait bound" is really just
* the trait. Basically like using an interface as a type in an OOP language. */
class TraitObjectTypeOneBound : public TypeNoBounds
{
bool has_dyn;
TraitBound trait_bound;
Location locus;
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
TraitObjectTypeOneBound *clone_type_no_bounds_impl () const override
{
return new TraitObjectTypeOneBound (*this);
}
public:
TraitObjectTypeOneBound (TraitBound trait_bound, Location locus,
bool is_dyn_dispatch = false)
: has_dyn (is_dyn_dispatch), trait_bound (std::move (trait_bound)),
locus (locus)
{}
std::string as_string () const override;
// Creates a trait bound (clone of this one's trait bound) - HACK
TraitBound *to_trait_bound (bool) const override
{
/* NOTE: this assumes there is no dynamic dispatch specified- if there was,
* this cloning would not be required as parsing is unambiguous. */
return new TraitBound (trait_bound);
}
Location get_locus () const override final { return locus; }
void accept_vis (ASTVisitor &vis) override;
// TODO: would a "vis_type" be better?
TraitBound &get_trait_bound ()
{
// TODO: check to ensure invariants are met?
return trait_bound;
}
bool is_dyn () const { return has_dyn; }
};
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;
Location locus;
public:
// Returns whether the tuple type is the unit type, i.e. has no elements.
bool is_unit_type () const { return elems.empty (); }
TupleType (std::vector<std::unique_ptr<Type> > elems, Location locus)
: elems (std::move (elems)), locus (locus)
{}
// copy constructor with vector clone
TupleType (TupleType const &other) : locus (other.locus)
{
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;
Location get_locus () const override final { return locus; }
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
{
return elems;
}
protected:
/* 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
{
Location locus;
protected:
/* 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 (Location locus) : locus (locus) {}
std::string as_string () const override { return "! (never type)"; }
Location get_locus () const override final { return locus; }
void accept_vis (ASTVisitor &vis) override;
};
// A type consisting of a pointer without safety or liveness guarantees
class RawPointerType : public TypeNoBounds
{
public:
enum PointerType
{
MUT,
CONST
};
private:
PointerType pointer_type;
std::unique_ptr<TypeNoBounds> type;
Location locus;
public:
// Returns whether the pointer is mutable or constant.
PointerType get_pointer_type () const { return pointer_type; }
// Constructor requires pointer for polymorphism reasons
RawPointerType (PointerType pointer_type,
std::unique_ptr<TypeNoBounds> type_no_bounds, Location locus)
: pointer_type (pointer_type), type (std::move (type_no_bounds)),
locus (locus)
{}
// Copy constructor calls custom polymorphic clone function
RawPointerType (RawPointerType const &other)
: pointer_type (other.pointer_type),
type (other.type->clone_type_no_bounds ()), locus (other.locus)
{}
// overload assignment operator to use custom clone method
RawPointerType &operator= (RawPointerType const &other)
{
pointer_type = other.pointer_type;
type = other.type->clone_type_no_bounds ();
locus = other.locus;
return *this;
}
// default move semantics
RawPointerType (RawPointerType &&other) = default;
RawPointerType &operator= (RawPointerType &&other) = default;
std::string as_string () const override;
Location get_locus () const override final { return locus; }
void accept_vis (ASTVisitor &vis) override;
// TODO: would a "vis_type" be better?
std::unique_ptr<TypeNoBounds> &get_type_pointed_to ()
{
rust_assert (type != nullptr);
return type;
}
protected:
/* 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;
bool has_mut;
std::unique_ptr<TypeNoBounds> type;
Location locus;
public:
// Returns whether the reference is mutable or immutable.
bool is_mut () const { return has_mut; }
// Returns whether the reference has a lifetime.
bool has_lifetime () const { return !lifetime.is_error (); }
// Constructor
ReferenceType (bool is_mut, std::unique_ptr<TypeNoBounds> type_no_bounds,
Location locus, Lifetime lifetime = Lifetime::error ())
: lifetime (std::move (lifetime)), has_mut (is_mut),
type (std::move (type_no_bounds)), locus (locus)
{}
// Copy constructor with custom clone method
ReferenceType (ReferenceType const &other)
: lifetime (other.lifetime), has_mut (other.has_mut),
type (other.type->clone_type_no_bounds ()), locus (other.locus)
{}
// Operator overload assignment operator to custom clone the unique pointer
ReferenceType &operator= (ReferenceType const &other)
{
lifetime = other.lifetime;
has_mut = other.has_mut;
type = other.type->clone_type_no_bounds ();
locus = other.locus;
return *this;
}
// move constructors
ReferenceType (ReferenceType &&other) = default;
ReferenceType &operator= (ReferenceType &&other) = default;
std::string as_string () const override;
Location get_locus () const override final { return locus; }
void accept_vis (ASTVisitor &vis) override;
// TODO: would a "vis_type" be better?
std::unique_ptr<TypeNoBounds> &get_type_referenced ()
{
rust_assert (type != nullptr);
return type;
}
bool get_has_mut () const { return has_mut; }
Lifetime &get_lifetime () { return lifetime; }
std::unique_ptr<TypeNoBounds> &get_base_type () { return type; }
protected:
/* 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;
Location locus;
public:
// Constructor requires pointers for polymorphism
ArrayType (std::unique_ptr<Type> type, std::unique_ptr<Expr> array_size,
Location locus)
: elem_type (std::move (type)), size (std::move (array_size)), locus (locus)
{}
// Copy constructor requires deep copies of both unique pointers
ArrayType (ArrayType const &other)
: elem_type (other.elem_type->clone_type ()),
size (other.size->clone_expr ()), locus (other.locus)
{}
// Overload assignment operator to deep copy pointers
ArrayType &operator= (ArrayType const &other)
{
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;
Location get_locus () const override final { return locus; }
void accept_vis (ASTVisitor &vis) override;
// TODO: would a "vis_type" be better?
std::unique_ptr<Type> &get_elem_type ()
{
rust_assert (elem_type != nullptr);
return elem_type;
}
// TODO: would a "vis_expr" be better?
std::unique_ptr<Expr> &get_size_expr ()
{
rust_assert (size != nullptr);
return size;
}
protected:
/* 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;
Location locus;
public:
// Constructor requires pointer for polymorphism
SliceType (std::unique_ptr<Type> type, Location locus)
: elem_type (std::move (type)), locus (locus)
{}
// Copy constructor requires deep copy of Type smart pointer
SliceType (SliceType const &other)
: elem_type (other.elem_type->clone_type ()), locus (other.locus)
{}
// Overload assignment operator to deep copy
SliceType &operator= (SliceType const &other)
{
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;
Location get_locus () const override final { return locus; }
void accept_vis (ASTVisitor &vis) override;
// TODO: would a "vis_type" be better?
std::unique_ptr<Type> &get_elem_type ()
{
rust_assert (elem_type != nullptr);
return elem_type;
}
protected:
/* 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
{
Location locus;
// e.g. Vec<_> = whatever
protected:
/* 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 (Location locus) : locus (locus) {}
std::string as_string () const override;
Location get_locus () const override final { return locus; }
void accept_vis (ASTVisitor &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::vector<Attribute> outer_attrs;
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,
std::vector<Attribute> outer_attrs, Location locus)
: outer_attrs (std::move (outer_attrs)),
param_type (std::move (param_type)), param_kind (param_kind),
name (std::move (name)), locus (locus)
{}
// Copy constructor with clone
MaybeNamedParam (MaybeNamedParam const &other)
: outer_attrs (other.outer_attrs), param_kind (other.param_kind),
name (other.name), locus (other.locus)
{
// guard to prevent null dereference
if (other.param_type != nullptr)
param_type = other.param_type->clone_type ();
}
~MaybeNamedParam () = default;
// Overloaded assignment operator with clone
MaybeNamedParam &operator= (MaybeNamedParam const &other)
{
outer_attrs = other.outer_attrs;
name = other.name;
param_kind = other.param_kind;
locus = other.locus;
// guard to prevent null dereference
if (other.param_type != nullptr)
param_type = other.param_type->clone_type ();
else
param_type = nullptr;
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; }
// TODO: this mutable getter seems really dodgy. Think up better way.
std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
// TODO: would a "vis_type" be better?
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::vector<Attribute> variadic_attrs;
// bool has_return_type;
// BareFunctionReturnType return_type;
std::unique_ptr<TypeNoBounds> return_type; // inlined version
Location locus;
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 (); }
std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; }
bool is_variadic () const { return _is_variadic; }
std::vector<Attribute> &get_variadic_attr () { return variadic_attrs; };
const std::vector<Attribute> &get_variadic_attr () const
{
return variadic_attrs;
};
BareFunctionType (std::vector<LifetimeParam> lifetime_params,
FunctionQualifiers qualifiers,
std::vector<MaybeNamedParam> named_params, bool is_variadic,
std::vector<Attribute> variadic_attrs,
std::unique_ptr<TypeNoBounds> type, Location locus)
: for_lifetimes (std::move (lifetime_params)),
function_qualifiers (std::move (qualifiers)),
params (std::move (named_params)), _is_variadic (is_variadic),
variadic_attrs (std::move (variadic_attrs)),
return_type (std::move (type)), locus (locus)
{
if (!variadic_attrs.empty ())
is_variadic = true;
}
// Copy constructor with clone
BareFunctionType (BareFunctionType const &other)
: for_lifetimes (other.for_lifetimes),
function_qualifiers (other.function_qualifiers), params (other.params),
_is_variadic (other._is_variadic), variadic_attrs (other.variadic_attrs),
locus (other.locus)
{
// guard to prevent null dereference
if (other.return_type != nullptr)
return_type = other.return_type->clone_type_no_bounds ();
}
// Overload assignment operator to deep copy
BareFunctionType &operator= (BareFunctionType const &other)
{
for_lifetimes = other.for_lifetimes;
function_qualifiers = other.function_qualifiers;
params = other.params;
_is_variadic = other._is_variadic;
variadic_attrs = other.variadic_attrs;
locus = other.locus;
// guard to prevent null dereference
if (other.return_type != nullptr)
return_type = other.return_type->clone_type_no_bounds ();
else
return_type = nullptr;
return *this;
}
// move constructors
BareFunctionType (BareFunctionType &&other) = default;
BareFunctionType &operator= (BareFunctionType &&other) = default;
std::string as_string () const override;
Location get_locus () const override final { return locus; }
void accept_vis (ASTVisitor &vis) override;
// TODO: this mutable getter seems kinda dodgy
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<TypeNoBounds> &get_return_type ()
{
rust_assert (has_return_type ());
return return_type;
}
FunctionQualifiers &get_function_qualifiers () { return function_qualifiers; }
protected:
/* 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);
}
};
// Forward decl - defined in rust-macro.h
class MacroInvocation;
/* 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 AST
} // namespace Rust
#endif