From: Owen Avery Date: Sat, 18 Mar 2023 05:41:01 +0000 (-0400) Subject: gccrs: Add lowering for if-let expressions X-Git-Tag: basepoints/gcc-15~2662 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=197962cb062edb41538af9f5e9b4c02f090c4ba8;p=thirdparty%2Fgcc.git gccrs: Add lowering for if-let expressions gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Add implementation for IfLetExprConseqElse. * typecheck/rust-hir-type-check-expr.h: (TypeCheckExpr::visit): Remove stub implementation for IfLetExprConseqElse. * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Lower IfLetExpr{,ConseqElse}. * hir/rust-ast-lower-expr.h: (ASTLoweringExpr::visit): Likewise. * hir/rust-ast-lower-block.h (ASTLoweringIfLetBlock::visit): Lower IfLetExprConseqElse. (ASTLoweringExprWithBlock::visit): Likewise. * hir/rust-ast-lower.cc (ASTLoweringIfLetBlock::visit): Lower IfLetExprConseqElse. * hir/tree/rust-hir-expr.h (IfLetExprConseqElse::IfLetExprConseqElse): Make constructor more general. (IfLetExprConseqElse::vis_else_block): Add. (IfLetExprConseqElse::get_else_block): Add. * resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit): Add IfLetExprConseqElse visitor. * resolve/rust-ast-resolve-expr.h (ResolveExpr::visit): Add IfLetExprConseqElse visitor. gcc/testsuite/ChangeLog: * rust/compile/if_let_expr.rs: Increase test coverage. Signed-off-by: Owen Avery --- diff --git a/gcc/rust/hir/rust-ast-lower-block.h b/gcc/rust/hir/rust-ast-lower-block.h index a12fd87956c8..a4d6069b7634 100644 --- a/gcc/rust/hir/rust-ast-lower-block.h +++ b/gcc/rust/hir/rust-ast-lower-block.h @@ -130,6 +130,8 @@ public: void visit (AST::IfLetExpr &expr) override; + void visit (AST::IfLetExprConseqElse &expr) override; + private: ASTLoweringIfLetBlock () : ASTLoweringBase (), translated (nullptr) {} @@ -172,6 +174,11 @@ public: translated = ASTLoweringIfLetBlock::translate (&expr); } + void visit (AST::IfLetExprConseqElse &expr) override + { + translated = ASTLoweringIfLetBlock::translate (&expr); + } + void visit (AST::BlockExpr &expr) override { translated = ASTLoweringBlock::translate (&expr, &terminated); diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc b/gcc/rust/hir/rust-ast-lower-expr.cc index c65b08e68400..31b7f0f49058 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.cc +++ b/gcc/rust/hir/rust-ast-lower-expr.cc @@ -103,6 +103,18 @@ ASTLoweringExpr::visit (AST::IfExprConseqElse &expr) translated = ASTLoweringIfBlock::translate (&expr, &terminated); } +void +ASTLoweringExpr::visit (AST::IfLetExpr &expr) +{ + translated = ASTLoweringIfLetBlock::translate (&expr); +} + +void +ASTLoweringExpr::visit (AST::IfLetExprConseqElse &expr) +{ + translated = ASTLoweringIfLetBlock::translate (&expr); +} + void ASTLoweringExpr::visit (AST::BlockExpr &expr) { diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index d3e95324145c..5b86ea292a0c 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -78,6 +78,8 @@ public: void visit (AST::TupleExpr &expr) override; void visit (AST::IfExpr &expr) override; void visit (AST::IfExprConseqElse &expr) override; + void visit (AST::IfLetExpr &expr) override; + void visit (AST::IfLetExprConseqElse &expr) override; void visit (AST::BlockExpr &expr) override; void visit (AST::UnsafeBlockExpr &expr) override; void visit (AST::PathInExpression &expr) override; diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index c9d5d01a7b14..cf5b75a12bdf 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -227,6 +227,40 @@ ASTLoweringIfLetBlock::visit (AST::IfLetExpr &expr) expr.get_locus ()); } +void +ASTLoweringIfLetBlock::visit (AST::IfLetExprConseqElse &expr) +{ + std::vector> patterns; + for (auto &pattern : expr.get_patterns ()) + { + HIR::Pattern *ptrn = ASTLoweringPattern::translate (pattern.get ()); + patterns.push_back (std::unique_ptr (ptrn)); + } + HIR::Expr *value_ptr + = ASTLoweringExpr::translate (expr.get_value_expr ().get ()); + + bool ignored_terminated = false; + HIR::BlockExpr *block + = ASTLoweringBlock::translate (expr.get_if_block ().get (), + &ignored_terminated); + + HIR::ExprWithBlock *else_block + = ASTLoweringExprWithBlock::translate (expr.get_else_block ().get (), + &ignored_terminated); + + rust_assert (else_block); + + 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 (value_ptr), + std::unique_ptr (block), + std::unique_ptr (else_block), expr.get_locus ()); +} + // rust-ast-lower-struct-field-expr.h void diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 3c9db9f9d8bf..47b989757faa 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -3457,7 +3457,7 @@ public: Analysis::NodeMapping mappings, std::vector > match_arm_patterns, std::unique_ptr value, std::unique_ptr if_block, - std::unique_ptr else_block, Location locus) + std::unique_ptr else_block, Location locus) : IfLetExpr (std::move (mappings), std::move (match_arm_patterns), std::move (value), std::move (if_block), locus), else_block (std::move (else_block)) @@ -3489,6 +3489,10 @@ public: void accept_vis (HIRFullVisitor &vis) override; void accept_vis (HIRExpressionVisitor &vis) override; + void vis_else_block (HIRFullVisitor &vis) { else_block->accept_vis (vis); } + + ExprWithBlock *get_else_block () { return else_block.get (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc index 339fd8a421b3..41ce9c9d0fe1 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.cc +++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc @@ -216,6 +216,37 @@ ResolveExpr::visit (AST::IfLetExpr &expr) resolver->get_label_scope ().pop (); } +void +ResolveExpr::visit (AST::IfLetExprConseqElse &expr) +{ + ResolveExpr::go (expr.get_value_expr ().get (), prefix, canonical_prefix); + + NodeId scope_node_id = expr.get_node_id (); + resolver->get_name_scope ().push (scope_node_id); + resolver->get_type_scope ().push (scope_node_id); + resolver->get_label_scope ().push (scope_node_id); + resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); + resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); + resolver->push_new_label_rib (resolver->get_type_scope ().peek ()); + + // We know expr.get_patterns () has one pattern at most + // so there's no reason to handle it like an AltPattern. + std::vector bindings + = {PatternBinding (PatternBoundCtx::Product, std::set ())}; + + for (auto &pattern : expr.get_patterns ()) + { + PatternDeclaration::go (pattern.get (), Rib::ItemType::Var, bindings); + } + + ResolveExpr::go (expr.get_if_block ().get (), prefix, canonical_prefix); + ResolveExpr::go (expr.get_else_block ().get (), prefix, canonical_prefix); + + resolver->get_name_scope ().pop (); + resolver->get_type_scope ().pop (); + resolver->get_label_scope ().pop (); +} + void ResolveExpr::visit (AST::BlockExpr &expr) { diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 7b0beaf49dcd..896617cc7ff5 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -51,6 +51,7 @@ public: void visit (AST::IfExpr &expr) override; void visit (AST::IfExprConseqElse &expr) override; void visit (AST::IfLetExpr &expr) override; + void visit (AST::IfLetExprConseqElse &expr) override; void visit (AST::BlockExpr &expr) override; void visit (AST::UnsafeBlockExpr &expr) override; void visit (AST::ArrayElemsValues &elems) override; diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 4352dc9a4d51..6594068a1eba 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -493,6 +493,42 @@ TypeCheckExpr::visit (HIR::IfLetExpr &expr) 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 ()); + auto else_blk_resolved = TypeCheckExpr::Resolve (expr.get_else_block ()); + + 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) { diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 68c09c74cc7f..2ff320d6b7bb 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -45,6 +45,7 @@ public: 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; @@ -75,7 +76,6 @@ public: void visit (HIR::RangeToInclExpr &) override {} void visit (HIR::WhileLetLoopExpr &) override {} void visit (HIR::ForLoopExpr &) override {} - void visit (HIR::IfLetExprConseqElse &) override {} void visit (HIR::AwaitExpr &) override {} void visit (HIR::AsyncBlockExpr &) override {} diff --git a/gcc/testsuite/rust/compile/if_let_expr.rs b/gcc/testsuite/rust/compile/if_let_expr.rs index 31e301fa3a37..ffa367b69c34 100644 --- a/gcc/testsuite/rust/compile/if_let_expr.rs +++ b/gcc/testsuite/rust/compile/if_let_expr.rs @@ -1,12 +1,10 @@ -// { dg-options "-fsyntax-only" } - pub enum Option { None, Some(T), } fn main() { - let x = Option::Some(3); + let x = Option::Some(3); // { dg-warning "unused name" } let a = if let Option::Some(1) = x { 1 } else if x == Option::Some(2) {