Fix ICE during HIR lowering of ExprWithBlock MatchExpr

When we are lowering blocks using the visitor pattern we must use the
BaseClass of ExprWithBlock to abstract away the notion that this expr
has a block such that we can handle cases like a block expr vs expressions
with a block. This makes the usage of hir lowering of match expressions to
be recursive, if we had more fine grained visitors in the AST we could fix
these types of problems with compile time enforced interfaces.

Fixes #858
This commit is contained in:
Philip Herron 2022-04-19 12:40:39 +01:00
parent d17e0aa769
commit 5528001eca
4 changed files with 86 additions and 46 deletions

View File

@ -191,6 +191,8 @@ public:
void visit (AST::WhileLoopExpr &expr) override;
void visit (AST::MatchExpr &expr) override;
private:
ASTLoweringExprWithBlock ()
: ASTLoweringBase (), translated (nullptr), terminated (false)

View File

@ -674,52 +674,7 @@ public:
void visit (AST::MatchExpr &expr) override
{
HIR::Expr *branch_value
= ASTLoweringExpr::translate (expr.get_scrutinee_expr ().get ());
std::vector<HIR::MatchCase> match_arms;
for (auto &match_case : expr.get_match_cases ())
{
HIR::Expr *kase_expr
= ASTLoweringExpr::translate (match_case.get_expr ().get ());
HIR::Expr *kase_guard_expr = nullptr;
if (match_case.get_arm ().has_match_arm_guard ())
{
kase_guard_expr = ASTLoweringExpr::translate (
match_case.get_arm ().get_guard_expr ().get ());
}
std::vector<std::unique_ptr<HIR::Pattern> > match_arm_patterns;
for (auto &pattern : match_case.get_arm ().get_patterns ())
{
HIR::Pattern *ptrn = ASTLoweringPattern::translate (pattern.get ());
match_arm_patterns.push_back (std::unique_ptr<HIR::Pattern> (ptrn));
}
HIR::MatchArm arm (std::move (match_arm_patterns), expr.get_locus (),
std::unique_ptr<HIR::Expr> (kase_guard_expr),
match_case.get_arm ().get_outer_attrs ());
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::MatchCase kase (std::move (mapping), std::move (arm),
std::unique_ptr<HIR::Expr> (kase_expr));
match_arms.push_back (std::move (kase));
}
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::MatchExpr (mapping, std::unique_ptr<HIR::Expr> (branch_value),
std::move (match_arms), expr.get_inner_attrs (),
expr.get_outer_attrs (), expr.get_locus ());
translated = ASTLoweringExprWithBlock::translate (&expr, &terminated);
}
void visit (AST::RangeFromToExpr &expr) override

View File

@ -299,6 +299,57 @@ ASTLoweringExprWithBlock::visit (AST::WhileLoopExpr &expr)
expr.get_outer_attrs ());
}
void
ASTLoweringExprWithBlock::visit (AST::MatchExpr &expr)
{
HIR::Expr *branch_value
= ASTLoweringExpr::translate (expr.get_scrutinee_expr ().get ());
std::vector<HIR::MatchCase> match_arms;
for (auto &match_case : expr.get_match_cases ())
{
HIR::Expr *kase_expr
= ASTLoweringExpr::translate (match_case.get_expr ().get ());
HIR::Expr *kase_guard_expr = nullptr;
if (match_case.get_arm ().has_match_arm_guard ())
{
kase_guard_expr = ASTLoweringExpr::translate (
match_case.get_arm ().get_guard_expr ().get ());
}
std::vector<std::unique_ptr<HIR::Pattern> > match_arm_patterns;
for (auto &pattern : match_case.get_arm ().get_patterns ())
{
HIR::Pattern *ptrn = ASTLoweringPattern::translate (pattern.get ());
match_arm_patterns.push_back (std::unique_ptr<HIR::Pattern> (ptrn));
}
HIR::MatchArm arm (std::move (match_arm_patterns), expr.get_locus (),
std::unique_ptr<HIR::Expr> (kase_guard_expr),
match_case.get_arm ().get_outer_attrs ());
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::MatchCase kase (std::move (mapping), std::move (arm),
std::unique_ptr<HIR::Expr> (kase_expr));
match_arms.push_back (std::move (kase));
}
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::MatchExpr (mapping, std::unique_ptr<HIR::Expr> (branch_value),
std::move (match_arms), expr.get_inner_attrs (),
expr.get_outer_attrs (), expr.get_locus ());
}
// rust-ast-lower-expr.h
void

View File

@ -0,0 +1,32 @@
/* { dg-output "Result: 123\n" } */
extern "C" {
fn printf(s: *const i8, ...);
}
enum Foo<T> {
A,
B(T),
}
fn main() -> i32 {
let result = Foo::B(123);
match result {
Foo::A => unsafe {
let a = "A\n\0";
let b = a as *const str;
let c = b as *const i8;
printf(c);
},
Foo::B(x) => unsafe {
let a = "Result: %i\n\0";
let b = a as *const str;
let c = b as *const i8;
printf(c, x);
},
}
0
}