virtual void mark_for_strip () = 0;
virtual bool is_marked_for_strip () const = 0;
- NodeId get_node_id () const { return node_id; }
+
+ // TODO: put this in a virtual base class?
+ virtual NodeId get_node_id () const { return node_id; }
virtual Kind get_stmt_kind () = 0;
virtual location_t get_locus () const = 0;
- NodeId get_node_id () const { return node_id; }
+ // TODO: put this in a virtual base class?
+ virtual NodeId get_node_id () const { return node_id; }
virtual Type *reconstruct_impl () const = 0;
protected:
virtual bool is_marked_for_strip () const = 0;
virtual location_t get_locus () const = 0;
+
+ virtual NodeId get_node_id () const = 0;
};
// Item used in trait declarations - abstract base class
return *main_or_left_expr;
}
+ std::unique_ptr<Expr> &get_casted_expr_ptr ()
+ {
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
+ }
+
// TODO: is this better? Or is a "vis_block" better?
TypeNoBounds &get_type_to_cast_to ()
{
return *type_to_convert_to;
}
+ std::unique_ptr<TypeNoBounds> &get_type_to_cast_to_ptr ()
+ {
+ rust_assert (type_to_convert_to != nullptr);
+ return type_to_convert_to;
+ }
+
Expr::Kind get_expr_kind () const override { return Expr::Kind::TypeCast; }
protected:
return *closure_inner;
}
+ std::unique_ptr<Expr> &get_definition_expr_ptr ()
+ {
+ rust_assert (closure_inner != nullptr);
+ return closure_inner;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
location_t get_locus () const override final { return locus; }
+ // needed to override AssociatedItem::get_node_id
+ NodeId get_node_id () const override final { return VisItem::get_node_id (); }
+
void accept_vis (ASTVisitor &vis) override;
// Invalid if existing type is null, so base stripping on that.
location_t get_locus () const override final { return locus; }
+ // needed to override AssociatedItem::get_node_id
+ NodeId get_node_id () const override final { return VisItem::get_node_id (); }
+
void accept_vis (ASTVisitor &vis) override;
// Invalid if type or expression are null, so base stripping on that.
void
ExpandVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr)
{
+ NodeId old_expect = expr->get_node_id ();
+ std::swap (macro_invoc_expect_id, old_expect);
+
expander.push_context (MacroExpander::ContextType::EXPR);
expr->accept_vis (*this);
expander.pop_context ();
+ std::swap (macro_invoc_expect_id, old_expect);
+
auto final_fragment = expander.take_expanded_fragment ();
if (final_fragment.should_expand ()
&& final_fragment.is_expression_fragment ())
void
ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::Type> &type)
{
- expander.push_context (MacroExpander::ContextType::TYPE);
+ NodeId old_expect = type->get_node_id ();
+ std::swap (macro_invoc_expect_id, old_expect);
+ expander.push_context (MacroExpander::ContextType::TYPE);
type->accept_vis (*this);
+ expander.pop_context ();
+
+ std::swap (macro_invoc_expect_id, old_expect);
+
auto final_fragment = expander.take_expanded_fragment ();
if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
type = final_fragment.take_type_fragment ();
+}
+
+// HACK: maybe we shouldn't have TypeNoBounds as a base class
+void
+ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type)
+{
+ NodeId old_expect = type->get_node_id ();
+ std::swap (macro_invoc_expect_id, old_expect);
+ expander.push_context (MacroExpander::ContextType::TYPE);
+ type->accept_vis (*this);
expander.pop_context ();
+
+ std::swap (macro_invoc_expect_id, old_expect);
+
+ auto final_fragment = expander.take_expanded_fragment ();
+ if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
+ type = std::make_unique<AST::ParenthesisedType> (
+ final_fragment.take_type_fragment (), BUILTINS_LOCATION);
}
// FIXME: Can this be refactored into a `scoped` method? Which takes a
void
ExpandVisitor::visit (AST::MacroInvocation ¯o_invoc)
{
+ if (macro_invoc_expect_id != macro_invoc.get_node_id ())
+ {
+ rust_internal_error_at (
+ macro_invoc.get_locus (),
+ "attempting to expand node with id %d into position with node id %d",
+ (int) macro_invoc.get_node_id (), (int) macro_invoc_expect_id);
+ }
+
// TODO: Can we do the AST fragment replacing here? Probably not, right?
expander.expand_invoc (macro_invoc, macro_invoc.has_semicolon ()
? AST::InvocKind::Semicoloned
maybe_expand_expr (expr.get_right_expr_ptr ());
}
+void
+ExpandVisitor::visit (AST::TypeCastExpr &expr)
+{
+ maybe_expand_expr (expr.get_casted_expr_ptr ());
+ maybe_expand_type (expr.get_type_to_cast_to_ptr ());
+}
+
void
ExpandVisitor::visit (AST::AssignmentExpr &expr)
{
{
expand_closure_params (expr.get_params ());
- visit (expr.get_definition_expr ());
+ maybe_expand_expr (expr.get_definition_expr_ptr ());
}
void
class ExpandVisitor : public AST::DefaultASTVisitor
{
public:
- ExpandVisitor (MacroExpander &expander) : expander (expander) {}
+ ExpandVisitor (MacroExpander &expander)
+ : expander (expander), macro_invoc_expect_id (UNKNOWN_NODEID)
+ {}
/* Expand all of the macro invocations currently contained in a crate */
void go (AST::Crate &crate);
type : Core guidelines R33, this function reseat the pointer.
*/
void maybe_expand_type (std::unique_ptr<AST::Type> &type);
+ void maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type);
/**
* Expand all macro invocations in lieu of types within a vector of struct
auto &value = *it;
// Perform expansion
+ NodeId old_expect = value->get_node_id ();
+ std::swap (macro_invoc_expect_id, old_expect);
value->accept_vis (*this);
+ std::swap (macro_invoc_expect_id, old_expect);
auto final_fragment = expander.take_expanded_fragment ();
void visit (AST::ArithmeticOrLogicalExpr &expr) override;
void visit (AST::ComparisonExpr &expr) override;
void visit (AST::LazyBooleanExpr &expr) override;
+ void visit (AST::TypeCastExpr &expr) override;
void visit (AST::AssignmentExpr &expr) override;
void visit (AST::CompoundAssignmentExpr &expr) override;
void visit (AST::GroupedExpr &expr) override;
private:
MacroExpander &expander;
+ NodeId macro_invoc_expect_id;
};
} // namespace Rust
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "fn_once"]
+trait FnOnce<Args> {
+ #[lang = "fn_once_output"]
+ type Output;
+
+ extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
macro_rules! closure {
() => {{
14 + 15