void visit (HIR::LoopExpr &) override {}
void visit (HIR::WhileLoopExpr &) override {}
void visit (HIR::WhileLetLoopExpr &) override {}
- void visit (HIR::IfLetExpr &) override {}
- void visit (HIR::IfLetExprConseqElse &) override {}
void visit (HIR::MatchExpr &) override {}
void visit (HIR::AwaitExpr &) override {}
void visit (HIR::AsyncBlockExpr &) override {}
void visit (HIR::LoopExpr &) override {}
void visit (HIR::WhileLoopExpr &) override {}
void visit (HIR::WhileLetLoopExpr &) override {}
- void visit (HIR::IfLetExpr &) override {}
- void visit (HIR::IfLetExprConseqElse &) override {}
void visit (HIR::MatchExpr &) override {}
void visit (HIR::AwaitExpr &) override {}
void visit (HIR::AsyncBlockExpr &) override {}
// TODO
// these need to be sugared in the HIR to if statements and a match
void visit (HIR::WhileLetLoopExpr &) override {}
- void visit (HIR::IfLetExpr &) override {}
- void visit (HIR::IfLetExprConseqElse &) override {}
// lets not worry about async yet....
void visit (HIR::AwaitExpr &) override {}
add_jump (else_end_bb, final_start_bb);
}
-void
-ExprStmtBuilder::visit (HIR::IfLetExpr &expr)
-{
- rust_sorry_at (expr.get_locus (), "if let expressions are not supported");
-}
-
-void
-ExprStmtBuilder::visit (HIR::IfLetExprConseqElse &expr)
-{
- rust_sorry_at (expr.get_locus (), "if let expressions are not supported");
-}
-
void
ExprStmtBuilder::visit (HIR::MatchExpr &expr)
{
void visit (HIR::IfExprConseqElse &expr) override;
void visit (HIR::InlineAsm &expr) override;
- void visit (HIR::IfLetExpr &expr) override;
- void visit (HIR::IfLetExprConseqElse &expr) override;
void visit (HIR::MatchExpr &expr) override;
void visit (HIR::AwaitExpr &expr) override;
void visit (HIR::AsyncBlockExpr &expr) override;
{
return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ());
}
- void visit (HIR::IfLetExpr &expr) override
- {
- return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ());
- }
- void visit (HIR::IfLetExprConseqElse &expr) override
- {
- return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ());
- }
void visit (HIR::MatchExpr &expr) override
{
return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ());
void visit (HIR::WhileLetLoopExpr &expr) override { rust_unreachable (); }
void visit (HIR::IfExpr &expr) override { rust_unreachable (); }
void visit (HIR::IfExprConseqElse &expr) override { rust_unreachable (); }
- void visit (HIR::IfLetExpr &expr) override { rust_unreachable (); }
- void visit (HIR::IfLetExprConseqElse &expr) override { rust_unreachable (); }
void visit (HIR::MatchExpr &expr) override { rust_unreachable (); }
void visit (HIR::AwaitExpr &expr) override { rust_unreachable (); }
void visit (HIR::AsyncBlockExpr &expr) override { rust_unreachable (); }
void visit (HIR::WhileLetLoopExpr &expr) override {}
void visit (HIR::IfExpr &expr) override {}
void visit (HIR::IfExprConseqElse &expr) override {}
- void visit (HIR::IfLetExpr &expr) override {}
- void visit (HIR::IfLetExprConseqElse &expr) override {}
void visit (HIR::MatchExpr &expr) override {}
void visit (HIR::AwaitExpr &expr) override {}
void visit (HIR::AsyncBlockExpr &expr) override {}
expr.get_else_block ()->accept_vis (*this);
}
-void
-PrivacyReporter::visit (HIR::IfLetExpr &)
-{
- // TODO: We need to visit the if_let_expr
- // TODO: We need to visit the block as well
-}
-
-void
-PrivacyReporter::visit (HIR::IfLetExprConseqElse &)
-{
- // TODO: We need to visit the if_let_expr
- // TODO: We need to visit the if_block as well
- // TODO: We need to visit the else_block as well
-}
-
void
PrivacyReporter::visit (HIR::MatchExpr &expr)
{
virtual void visit (HIR::WhileLetLoopExpr &expr);
virtual void visit (HIR::IfExpr &expr);
virtual void visit (HIR::IfExprConseqElse &expr);
- virtual void visit (HIR::IfLetExpr &expr);
- virtual void visit (HIR::IfLetExprConseqElse &expr);
virtual void visit (HIR::MatchExpr &expr);
virtual void visit (HIR::AwaitExpr &expr);
virtual void visit (HIR::AsyncBlockExpr &expr);
expr.get_else_block ()->accept_vis (*this);
}
-void
-ConstChecker::visit (IfLetExpr &expr)
-{
- expr.get_scrutinee_expr ()->accept_vis (*this);
- expr.get_if_block ()->accept_vis (*this);
-}
-
-void
-ConstChecker::visit (IfLetExprConseqElse &expr)
-{
- expr.get_scrutinee_expr ()->accept_vis (*this);
- expr.get_if_block ()->accept_vis (*this);
-
- // TODO: Visit else expression
-}
-
void
ConstChecker::visit (MatchExpr &expr)
{
virtual void visit (WhileLetLoopExpr &expr) override;
virtual void visit (IfExpr &expr) override;
virtual void visit (IfExprConseqElse &expr) override;
- virtual void visit (IfLetExpr &expr) override;
- virtual void visit (IfLetExprConseqElse &expr) override;
virtual void visit (MatchExpr &expr) override;
virtual void visit (AwaitExpr &expr) override;
virtual void visit (AsyncBlockExpr &expr) override;
expr.get_else_block ()->accept_vis (*this);
}
-void
-PatternChecker::visit (IfLetExpr &expr)
-{
- expr.get_scrutinee_expr ()->accept_vis (*this);
- expr.get_if_block ()->accept_vis (*this);
-}
-
-void
-PatternChecker::visit (IfLetExprConseqElse &expr)
-{
- expr.get_scrutinee_expr ()->accept_vis (*this);
- expr.get_if_block ()->accept_vis (*this);
-
- expr.get_else_block ()->accept_vis (*this);
-}
-
void
PatternChecker::visit (MatchExpr &expr)
{
virtual void visit (WhileLetLoopExpr &expr) override;
virtual void visit (IfExpr &expr) override;
virtual void visit (IfExprConseqElse &expr) override;
- virtual void visit (IfLetExpr &expr) override;
- virtual void visit (IfLetExprConseqElse &expr) override;
virtual void visit (HIR::MatchExpr &expr) override;
virtual void visit (AwaitExpr &expr) override;
virtual void visit (AsyncBlockExpr &expr) override;
expr.get_else_block ()->accept_vis (*this);
}
-void
-UnsafeChecker::visit (IfLetExpr &expr)
-{
- expr.get_scrutinee_expr ()->accept_vis (*this);
- expr.get_if_block ()->accept_vis (*this);
-}
-
-void
-UnsafeChecker::visit (IfLetExprConseqElse &expr)
-{
- expr.get_scrutinee_expr ()->accept_vis (*this);
- expr.get_if_block ()->accept_vis (*this);
-
- // TODO: Visit else expression
-}
-
void
UnsafeChecker::visit (MatchExpr &expr)
{
virtual void visit (WhileLetLoopExpr &expr) override;
virtual void visit (IfExpr &expr) override;
virtual void visit (IfExprConseqElse &expr) override;
- virtual void visit (IfLetExpr &expr) override;
- virtual void visit (IfLetExprConseqElse &expr) override;
virtual void visit (MatchExpr &expr) override;
virtual void visit (AwaitExpr &expr) override;
virtual void visit (AsyncBlockExpr &expr) override;
using Rust::HIR::ASTLoweringBase::visit;
public:
- static HIR::IfLetExpr *translate (AST::IfLetExpr &expr)
+ static HIR::MatchExpr *translate (AST::IfLetExpr &expr)
{
ASTLoweringIfLetBlock resolver;
expr.accept_vis (resolver);
private:
ASTLoweringIfLetBlock () : ASTLoweringBase (), translated (nullptr) {}
- HIR::IfLetExpr *translated;
+ void desugar_iflet (AST::IfLetExpr &, HIR::Expr **, HIR::Expr *,
+ std::vector<HIR::MatchCase> &);
+
+ HIR::MatchExpr *translated;
};
class ASTLoweringExprWithBlock : public ASTLoweringBase
ASTLoweringExprWithBlock resolver;
expr.accept_vis (resolver);
if (resolver.translated != nullptr)
- {
- resolver.mappings.insert_hir_expr (resolver.translated);
- }
+ resolver.mappings.insert_hir_expr (resolver.translated);
*terminated = resolver.terminated;
return resolver.translated;
#include "rust-ast-lower-type.h"
#include "rust-ast-lower-pattern.h"
#include "rust-ast-lower-struct-field-expr.h"
+#include "rust-expr.h"
+#include "rust-hir-expr.h"
namespace Rust {
namespace HIR {
std::unique_ptr<HIR::ExprWithBlock> (else_block), expr.get_locus ());
}
+/**
+ * Lowers the common part "if let 'pattern' = 'expr' { 'if_block' }" of
+ * IfLetExpr[ConseqElse]:
+ * - 'expr' is lowered into *BRANCH_VALUE
+ * - 'pattern' + 'if_block' are lowered and resulting ARM pushed in MATCH_ARMS
+ * - 'KASE_ELSE_EXPR' is the lowered HIR to be used in the else part.
+ *
+ * Looks like:
+ *
+ * match (expr) {
+ * pattern => {if_block}
+ * _ => kase_else_expr
+ * }
+ *
+ */
void
-ASTLoweringIfLetBlock::visit (AST::IfLetExpr &expr)
+ASTLoweringIfLetBlock::desugar_iflet (AST::IfLetExpr &expr,
+ HIR::Expr **branch_value,
+ HIR::Expr *kase_else_expr,
+ std::vector<HIR::MatchCase> &match_arms)
{
- std::vector<std::unique_ptr<HIR::Pattern>> patterns;
+ HIR::Expr *kase_expr;
+ std::vector<std::unique_ptr<HIR::Pattern>> match_arm_patterns;
+
+ *branch_value = ASTLoweringExpr::translate (expr.get_value_expr ());
+ kase_expr = ASTLoweringExpr::translate (expr.get_if_block ());
+
+ // (stable) if let only accepts a single pattern, but (unstable) if let chains
+ // need more than one pattern.
+ // We don't support if let chains, so only support a single pattern.
+ rust_assert (expr.get_patterns ().size () == 1);
+
for (auto &pattern : expr.get_patterns ())
{
HIR::Pattern *ptrn = ASTLoweringPattern::translate (*pattern);
- patterns.push_back (std::unique_ptr<HIR::Pattern> (ptrn));
+ match_arm_patterns.push_back (std::unique_ptr<HIR::Pattern> (ptrn));
}
- HIR::Expr *value_ptr = ASTLoweringExpr::translate (expr.get_value_expr ());
- bool ignored_terminated = false;
- HIR::BlockExpr *block
- = ASTLoweringBlock::translate (expr.get_if_block (), &ignored_terminated);
+ // The match arm corresponding to the if let pattern when it matches.
+ HIR::MatchArm arm (std::move (match_arm_patterns), expr.get_locus (), nullptr,
+ {});
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
mappings.get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);
- translated = new HIR::IfLetExpr (mapping, std::move (patterns),
- std::unique_ptr<HIR::Expr> (value_ptr),
- std::unique_ptr<HIR::BlockExpr> (block),
- expr.get_locus ());
+ HIR::MatchCase kase (std::move (mapping), std::move (arm),
+ std::unique_ptr<HIR::Expr> (kase_expr));
+ match_arms.push_back (std::move (kase));
+
+ // The default match arm when the if let pattern does not match
+ std::vector<std::unique_ptr<HIR::Pattern>> match_arm_patterns_wildcard;
+ Analysis::NodeMapping mapping_default (crate_num, expr.get_node_id (),
+ mappings.get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ std::unique_ptr<HIR::WildcardPattern> wc
+ = std::unique_ptr<HIR::WildcardPattern> (
+ new HIR::WildcardPattern (mapping_default, expr.get_locus ()));
+
+ match_arm_patterns_wildcard.push_back (std::move (wc));
+
+ HIR::MatchArm arm_default (std::move (match_arm_patterns_wildcard),
+ expr.get_locus (), nullptr, {});
+
+ HIR::MatchCase kase_else (std::move (mapping_default),
+ std::move (arm_default),
+ std::unique_ptr<HIR::Expr> (kase_else_expr));
+ match_arms.push_back (std::move (kase_else));
}
void
-ASTLoweringIfLetBlock::visit (AST::IfLetExprConseqElse &expr)
+ASTLoweringIfLetBlock::visit (AST::IfLetExpr &expr)
{
- std::vector<std::unique_ptr<HIR::Pattern>> patterns;
- for (auto &pattern : expr.get_patterns ())
- {
- HIR::Pattern *ptrn = ASTLoweringPattern::translate (*pattern);
- patterns.push_back (std::unique_ptr<HIR::Pattern> (ptrn));
- }
- HIR::Expr *value_ptr = ASTLoweringExpr::translate (expr.get_value_expr ());
+ // Desugar:
+ // if let Some(y) = some_value {
+ // bar();
+ // }
+ //
+ // into:
+ //
+ // match some_value {
+ // Some(y) => {bar();},
+ // _ => ()
+ // }
+
+ HIR::Expr *branch_value;
- bool ignored_terminated = false;
- HIR::BlockExpr *block
- = ASTLoweringBlock::translate (expr.get_if_block (), &ignored_terminated);
+ std::vector<HIR::MatchCase> match_arms;
+ auto crate_num = mappings.get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings.get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
- HIR::ExprWithBlock *else_block
- = ASTLoweringExprWithBlock::translate (expr.get_else_block (),
- &ignored_terminated);
+ HIR::TupleExpr *unit
+ = new HIR::TupleExpr (mapping, {}, {}, {}, expr.get_locus ());
+
+ desugar_iflet (expr, &branch_value, unit, match_arms);
- rust_assert (else_block);
+ translated
+ = new HIR::MatchExpr (mapping, std::unique_ptr<HIR::Expr> (branch_value),
+ std::move (match_arms), {}, {}, expr.get_locus ());
+}
+
+void
+ASTLoweringIfLetBlock::visit (AST::IfLetExprConseqElse &expr)
+{
+ // desugar:
+ // if let Some(y) = some_value {
+ // bar();
+ // } else {
+ // baz();
+ // }
+ //
+ // into
+ // match some_value {
+ // Some(y) => {bar();},
+ // _ => {baz();}
+ // }
+ //
+
+ HIR::Expr *branch_value;
+ std::vector<HIR::MatchCase> match_arms;
+
+ HIR::Expr *kase_else_expr
+ = ASTLoweringExpr::translate (expr.get_else_block ());
+
+ desugar_iflet (expr, &branch_value, kase_else_expr, match_arms);
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
mappings.get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);
- translated = new HIR::IfLetExprConseqElse (
- mapping, std::move (patterns), std::unique_ptr<HIR::Expr> (value_ptr),
- std::unique_ptr<HIR::BlockExpr> (block),
- std::unique_ptr<HIR::ExprWithBlock> (else_block), expr.get_locus ());
+ translated
+ = new HIR::MatchExpr (mapping, std::unique_ptr<HIR::Expr> (branch_value),
+ std::move (match_arms), {}, {}, expr.get_locus ());
}
// rust-ast-lower-struct-field-expr.h
Visibility
translate_visibility (const AST::Visibility &vis);
+/**
+ * Main base class used for lowering AST to HIR.
+ *
+ * Every subclass should provide a translate() method that takes an AST node and
+ * lowers it to some HIR stored in the TRANSLATED member. */
class ASTLowering
{
public:
visit_field ("loop_block", e.get_loop_block ());
}
-void
-Dump::do_ifletexpr (IfLetExpr &e)
-{
- do_expr (e);
-
- visit_collection ("match_arm_patterns", e.get_patterns ());
-
- visit_field ("value", e.get_scrutinee_expr ());
- visit_field ("if_block", e.get_if_block ());
-}
-
void
Dump::do_struct (Struct &e)
{
end ("IfExprConseqElse");
}
-void
-Dump::visit (IfLetExpr &e)
-{
- begin ("IfLetExpr");
- do_ifletexpr (e);
- end ("IfLetExpr");
-}
-
-void
-Dump::visit (IfLetExprConseqElse &e)
-{
- begin ("IfLetExprConseqElse");
- do_ifletexpr (e);
- visit_field ("else_block", e.get_else_block ());
- end ("IfLetExprConseqElse");
-}
-
void
Dump::visit (MatchExpr &e)
{
void do_type (Type &);
void do_expr (Expr &);
void do_ifexpr (IfExpr &);
- void do_ifletexpr (IfLetExpr &);
void do_pathexpr (PathExpr &);
void do_pathpattern (PathPattern &);
void do_genericargs (GenericArgs &);
virtual void visit (WhileLetLoopExpr &) override;
virtual void visit (IfExpr &) override;
virtual void visit (IfExprConseqElse &) override;
- virtual void visit (IfLetExpr &) override;
- virtual void visit (IfLetExprConseqElse &) override;
virtual void visit (MatchExpr &) override;
virtual void visit (AwaitExpr &) override;
// TODO: inline?
class LoopLabel /*: public Node*/
{
- Lifetime label; // or type LIFETIME_OR_LABEL
+ Lifetime label; // of type LIFETIME_OR_LABEL
location_t locus;
}
};
-// forward decl for IfExpr
-class IfLetExpr;
-
// Base if expression with no "else" or "if let" HIR node
class IfExpr : public ExprWithBlock
{
}
};
-// Basic "if let" expression HIR node with no else
-class IfLetExpr : public ExprWithBlock
-{
- // MatchArmPatterns patterns;
- std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
- std::unique_ptr<Expr> value;
- std::unique_ptr<BlockExpr> if_block;
-
- location_t locus;
-
-public:
- std::string as_string () const override;
-
- IfLetExpr (Analysis::NodeMapping mappings,
- std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
- std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block,
- location_t locus)
- : ExprWithBlock (std::move (mappings), AST::AttrVec ()),
- match_arm_patterns (std::move (match_arm_patterns)),
- value (std::move (value)), if_block (std::move (if_block)), locus (locus)
- {}
- // outer attributes not allowed on if let exprs either
-
- // copy constructor with clone
- IfLetExpr (IfLetExpr const &other)
- : ExprWithBlock (other),
- /*match_arm_patterns(other.match_arm_patterns),*/ value (
- other.value->clone_expr ()),
- if_block (other.if_block->clone_block_expr ()), locus (other.locus)
- {
- match_arm_patterns.reserve (other.match_arm_patterns.size ());
- for (const auto &e : other.match_arm_patterns)
- match_arm_patterns.push_back (e->clone_pattern ());
- }
-
- // overload assignment operator to clone
- IfLetExpr &operator= (IfLetExpr const &other)
- {
- ExprWithBlock::operator= (other);
- // match_arm_patterns = other.match_arm_patterns;
- value = other.value->clone_expr ();
- if_block = other.if_block->clone_block_expr ();
- locus = other.locus;
-
- match_arm_patterns.reserve (other.match_arm_patterns.size ());
- for (const auto &e : other.match_arm_patterns)
- match_arm_patterns.push_back (e->clone_pattern ());
-
- return *this;
- }
-
- // move constructors
- IfLetExpr (IfLetExpr &&other) = default;
- IfLetExpr &operator= (IfLetExpr &&other) = default;
-
- // Unique pointer custom clone function
- std::unique_ptr<IfLetExpr> clone_if_let_expr () const
- {
- return std::unique_ptr<IfLetExpr> (clone_if_let_expr_impl ());
- }
-
- location_t get_locus () const override final { return locus; }
-
- void accept_vis (HIRFullVisitor &vis) override;
- void accept_vis (HIRExpressionVisitor &vis) override;
-
- std::unique_ptr<Expr> &get_scrutinee_expr () { return value; }
-
- std::vector<std::unique_ptr<Pattern> > &get_patterns ()
- {
- return match_arm_patterns;
- }
-
- std::unique_ptr<BlockExpr> &get_if_block () { return if_block; }
-
- ExprType get_expression_type () const final override
- {
- return ExprType::IfLet;
- }
-
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfLetExpr *clone_expr_impl () const override { return new IfLetExpr (*this); }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfLetExpr *clone_expr_with_block_impl () const override
- {
- return new IfLetExpr (*this);
- }
-
- // Base clone function but still concrete as concrete base class
- virtual IfLetExpr *clone_if_let_expr_impl () const
- {
- return new IfLetExpr (*this);
- }
-};
-
-/* HIR node representing "if let" expression with an "else" expression at the
- * end */
-class IfLetExprConseqElse : public IfLetExpr
-{
- std::unique_ptr<ExprWithBlock> else_block;
-
-public:
- std::string as_string () const override;
-
- IfLetExprConseqElse (
- Analysis::NodeMapping mappings,
- std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
- std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block,
- std::unique_ptr<ExprWithBlock> else_block, location_t locus)
- : IfLetExpr (std::move (mappings), std::move (match_arm_patterns),
- std::move (value), std::move (if_block), locus),
- else_block (std::move (else_block))
- {}
- // outer attributes not allowed
-
- // copy constructor with clone
- IfLetExprConseqElse (IfLetExprConseqElse const &other)
- : IfLetExpr (other), else_block (other.else_block->clone_expr_with_block ())
- {}
-
- // overload assignment operator to clone
- IfLetExprConseqElse &operator= (IfLetExprConseqElse const &other)
- {
- IfLetExpr::operator= (other);
- // match_arm_patterns = other.match_arm_patterns;
- // value = other.value->clone_expr();
- // if_block = other.if_block->clone_block_expr();
- else_block = other.else_block->clone_expr_with_block ();
- // outer_attrs = other.outer_attrs;
-
- return *this;
- }
-
- // move constructors
- IfLetExprConseqElse (IfLetExprConseqElse &&other) = default;
- IfLetExprConseqElse &operator= (IfLetExprConseqElse &&other) = default;
-
- void accept_vis (HIRFullVisitor &vis) override;
- void accept_vis (HIRExpressionVisitor &vis) override;
-
- void vis_else_block (HIRFullVisitor &vis) { else_block->accept_vis (vis); }
-
- std::unique_ptr<ExprWithBlock> &get_else_block () { return else_block; }
-
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfLetExprConseqElse *clone_expr_impl () const override
- {
- return new IfLetExprConseqElse (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfLetExprConseqElse *clone_expr_with_block_impl () const override
- {
- return new IfLetExprConseqElse (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfLetExprConseqElse *clone_if_let_expr_impl () const override
- {
- return new IfLetExprConseqElse (*this);
- }
-};
-
// Match arm expression
struct MatchArm
{
class WhileLetLoopExpr;
class IfExpr;
class IfExprConseqElse;
-class IfLetExpr;
-class IfLetExprConseqElse;
struct MatchArm;
// class MatchCase;
// class MatchCaseBlockExpr;
virtual void visit (WhileLetLoopExpr &expr) = 0;
virtual void visit (IfExpr &expr) = 0;
virtual void visit (IfExprConseqElse &expr) = 0;
- virtual void visit (IfLetExpr &expr) = 0;
- virtual void visit (IfLetExprConseqElse &expr) = 0;
virtual void visit (MatchExpr &expr) = 0;
virtual void visit (AwaitExpr &expr) = 0;
virtual void visit (AsyncBlockExpr &expr) = 0;
virtual void visit (WhileLetLoopExpr &) override {}
virtual void visit (IfExpr &) override {}
virtual void visit (IfExprConseqElse &) override {}
- virtual void visit (IfLetExpr &) override {}
- virtual void visit (IfLetExprConseqElse &) override {}
virtual void visit (MatchExpr &) override {}
virtual void visit (AwaitExpr &) override {}
virtual void visit (WhileLetLoopExpr &expr) = 0;
virtual void visit (IfExpr &expr) = 0;
virtual void visit (IfExprConseqElse &expr) = 0;
- virtual void visit (IfLetExpr &expr) = 0;
- virtual void visit (IfLetExprConseqElse &expr) = 0;
virtual void visit (InlineAsm &expr) = 0;
virtual void visit (MatchExpr &expr) = 0;
virtual void visit (AwaitExpr &expr) = 0;
return str;
}
-std::string
-IfLetExpr::as_string () const
-{
- std::string str ("IfLetExpr: ");
-
- str += "\n Condition match arm patterns: ";
- if (match_arm_patterns.empty ())
- {
- str += "none";
- }
- else
- {
- for (const auto &pattern : match_arm_patterns)
- {
- str += "\n " + pattern->as_string ();
- }
- }
-
- str += "\n Scrutinee expr: " + value->as_string ();
-
- str += "\n If let block expr: " + if_block->as_string ();
-
- return str;
-}
-
-std::string
-IfLetExprConseqElse::as_string () const
-{
- std::string str = IfLetExpr::as_string ();
-
- str += "\n Else expr: " + else_block->as_string ();
-
- return str;
-}
-
std::string
RangeFromToInclExpr::as_string () const
{
vis.visit (*this);
}
-void
-IfLetExpr::accept_vis (HIRFullVisitor &vis)
-{
- vis.visit (*this);
-}
-
-void
-IfLetExprConseqElse::accept_vis (HIRFullVisitor &vis)
-{
- vis.visit (*this);
-}
-
void
MatchExpr::accept_vis (HIRFullVisitor &vis)
{
vis.visit (*this);
}
-void
-IfLetExprConseqElse::accept_vis (HIRExpressionVisitor &vis)
-{
- vis.visit (*this);
-}
-
-void
-IfLetExpr::accept_vis (HIRExpressionVisitor &vis)
-{
- vis.visit (*this);
-}
-
void
IfExprConseqElse::accept_vis (HIRExpressionVisitor &vis)
{
UnsafeBlock,
BaseLoop,
If,
- IfLet,
Match,
Await,
AsyncBlock,
}
}
-void
-TypeCheckExpr::visit (HIR::IfLetExpr &expr)
-{
- // this needs to perform a least upper bound coercion on the blocks and then
- // unify the scruintee and arms
- TyTy::BaseType *scrutinee_tyty
- = TypeCheckExpr::Resolve (expr.get_scrutinee_expr ().get ());
-
- for (auto &pattern : expr.get_patterns ())
- {
- TyTy::BaseType *kase_arm_ty
- = TypeCheckPattern::Resolve (pattern.get (), scrutinee_tyty);
-
- unify_site (expr.get_mappings ().get_hirid (),
- TyTy::TyWithLocation (scrutinee_tyty),
- TyTy::TyWithLocation (kase_arm_ty, pattern->get_locus ()),
- expr.get_locus ());
- }
-
- TypeCheckExpr::Resolve (expr.get_if_block ().get ());
-
- infered = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ());
-}
-
-void
-TypeCheckExpr::visit (HIR::IfLetExprConseqElse &expr)
-{
- TyTy::BaseType *scrutinee_tyty
- = TypeCheckExpr::Resolve (expr.get_scrutinee_expr ().get ());
-
- for (auto &pattern : expr.get_patterns ())
- {
- TyTy::BaseType *kase_arm_ty
- = TypeCheckPattern::Resolve (pattern.get (), scrutinee_tyty);
-
- unify_site (expr.get_mappings ().get_hirid (),
- TyTy::TyWithLocation (scrutinee_tyty),
- TyTy::TyWithLocation (kase_arm_ty, pattern->get_locus ()),
- expr.get_locus ());
- }
-
- auto if_blk_resolved = TypeCheckExpr::Resolve (expr.get_if_block ().get ());
- auto else_blk_resolved
- = TypeCheckExpr::Resolve (expr.get_else_block ().get ());
-
- if (if_blk_resolved->get_kind () == TyTy::NEVER)
- infered = else_blk_resolved;
- else if (else_blk_resolved->get_kind () == TyTy::NEVER)
- infered = if_blk_resolved;
- else
- {
- infered = unify_site (
- expr.get_mappings ().get_hirid (),
- TyTy::TyWithLocation (if_blk_resolved,
- expr.get_if_block ()->get_locus ()),
- TyTy::TyWithLocation (else_blk_resolved,
- expr.get_else_block ()->get_locus ()),
- expr.get_locus ());
- }
-}
-
void
TypeCheckExpr::visit (HIR::UnsafeBlockExpr &expr)
{
void visit (HIR::NegationExpr &expr) override;
void visit (HIR::IfExpr &expr) override;
void visit (HIR::IfExprConseqElse &expr) override;
- void visit (HIR::IfLetExpr &expr) override;
- void visit (HIR::IfLetExprConseqElse &) override;
void visit (HIR::BlockExpr &expr) override;
void visit (HIR::UnsafeBlockExpr &expr) override;
void visit (HIR::ArrayIndexExpr &expr) override;
}
fn main() {
- let x = Option::Some(3); // { dg-warning "unused name" }
- let a = if let Option::Some(1) = x {
+ let x = Option::Some(3);
+
+ let a = if let Option::Some(1) = x {// { dg-warning "unused name" }
1
} else if x == Option::Some(2) {
2
--- /dev/null
+enum MyOption {
+ Some(i32),
+ None,
+}
+
+pub fn toto(i : MyOption) -> i32 {
+ if let MyOption::Some(v) = i {
+ v
+ } else {
+ 23i32
+ }
+}
--- /dev/null
+pub fn simple_iflet() -> i32 {
+ let mut res = 0;
+
+ enum E {
+ X(i32),
+ }
+ let v = E::X(4);
+
+ if let E::X(n) = v {
+ res = 1;
+ }
+
+ res
+}
+
+pub fn simple_iflet_else() -> i32 {
+ let mut res = 0;
+
+ enum E {
+ X(i32),
+ Y,
+ }
+ let v = E::X(4);
+
+ if let E::Y = v {
+ res = 1;
+ } else {
+ res = 2;
+ }
+
+ res
+}
issue-2499.rs
issue-3032-1.rs
issue-3032-2.rs
+# https://github.com/Rust-GCC/gccrs/issues/3189
+if_let_expr_simple.rs
+iflet.rs
# please don't delete the trailing newline
--- /dev/null
+enum Res {
+ OK,
+ BAD,
+}
+
+enum LOption {
+ Some(i32),
+ None,
+}
+
+// Expect a Some(_)
+//
+// Check we can match a Some.
+fn test_can_destructure_Some(v: LOption) -> Res {
+ if let LOption::Some(v) = v {
+ return Res::OK;
+ }
+ return Res::BAD;
+}
+
+// Expect Some(100).
+//
+// Check we can destructure and the inner value is correct.
+fn test_inner_value_is_100(v: LOption) -> Res {
+ if let LOption::Some(v) = v {
+ return match v {
+ 100 => Res::OK,
+ _ => Res::BAD,
+ }
+ }
+ return Res::BAD;
+}
+
+// Expect a None as actual parameter.
+//
+// Only when we FAIL to match a Some do we take the else and return OK.
+fn test_if_else(v: LOption) -> Res {
+ if let LOption::Some(v) = v {
+ return Res::BAD;
+ } else {
+ return Res::OK;
+ }
+}
+
+fn main() -> i32 {
+
+ // Passing a None, so the function should return BAD
+ match test_can_destructure_Some(LOption::None) {
+ Res::OK => return 1,
+ Res::BAD => (),
+ }
+
+ // Same, but with a Some, should return OK
+ match test_can_destructure_Some(LOption::Some(1)) {
+ Res::OK => (),
+ Res::BAD => return 1,
+ }
+
+ // Check the destructuring is correct by looking for Some(100)
+ match test_inner_value_is_100(LOption::Some(100)) {
+ Res::OK => (),
+ Res::BAD => return 1,
+ }
+
+ // ... passing Some(1) should return BAD
+ match test_inner_value_is_100(LOption::Some(1)) {
+ Res::OK => return 1,
+ Res::BAD => (),
+ }
+
+ // ... and so does passing None
+ match test_inner_value_is_100(LOption::None) {
+ Res::OK => return 1,
+ Res::BAD => (),
+ }
+
+ // Check if let... else ...
+ match test_if_else(LOption::None) {
+ Res::OK => (),
+ Res::BAD => return 1,
+ }
+
+ 0
+}