hax_rust_engine/phase/
reject_not_do_lean_dsl.rs1use crate::ast::*;
2use crate::ast::{diagnostics::*, visitors::*};
3use crate::phase::Phase;
4
5#[derive(Default)]
10pub struct RejectNotDoLeanDSL;
11
12#[derive(Clone, Copy, Debug)]
15enum DoDSLExprKind {
16 Statement,
17 Expression,
18}
19
20fn dsl_expr_kind(expr_kind: &ExprKind) -> DoDSLExprKind {
22 match expr_kind {
23 ExprKind::If { .. } | ExprKind::Match { .. } | ExprKind::Let { .. } => {
24 DoDSLExprKind::Statement
25 }
26 _ => DoDSLExprKind::Expression,
27 }
28}
29
30impl Default for DoDSLExprKind {
32 fn default() -> Self {
33 Self::Statement
34 }
35}
36
37#[setup_error_handling_struct]
39#[derive(Default)]
40pub struct RejectNotDoLeanDSLVisitor {
41 dsl_expr_kind: DoDSLExprKind,
43}
44
45impl VisitorWithContext for RejectNotDoLeanDSLVisitor {
46 fn context(&self) -> Context {
47 Context::Phase(stringify!(RejectNotDoLeanDSL).to_string())
48 }
49}
50
51impl AstVisitorMut for RejectNotDoLeanDSLVisitor {
52 setup_error_handling_impl!();
53
54 fn visit_expr(&mut self, expr: &mut Expr) {
55 use DoDSLExprKind::*;
56 let parent_dsl_expr_kind = self.dsl_expr_kind;
57 self.dsl_expr_kind = match (self.dsl_expr_kind, dsl_expr_kind(&expr.kind)) {
58 (Expression, Statement) => {
60 self.error(
61 expr.clone(),
62 DiagnosticInfoKind::ExplicitRejection {
63 reason: "This interleaving of expression and statements does not fit in Lean's do-notation DSL.\
64 \nYou may try hoisting out let-bindings and control-flow.".to_string(),
65 issue_id: Some(1741),
66 },
67 );
68 Statement
69 }
70 (_, _) if matches!(&*expr.kind, ExprKind::Closure { .. }) => Statement,
72 (_, kind) => kind,
74 };
75 self.visit_inner(expr);
76 self.dsl_expr_kind = parent_dsl_expr_kind;
77 }
78
79 fn visit_ty(&mut self, ty: &mut Ty) {
82 if let TyKind::Array { length, .. } = ty.kind_mut() {
83 let parent_dsl_expr_kind = self.dsl_expr_kind;
87 self.dsl_expr_kind = DoDSLExprKind::Expression;
88 self.visit_inner(&mut *length);
89 self.dsl_expr_kind = parent_dsl_expr_kind;
90 }
91 }
92}
93
94impl Phase for RejectNotDoLeanDSL {
95 fn apply(&self, items: &mut Vec<Item>) {
96 RejectNotDoLeanDSLVisitor::default().visit(items)
98 }
99}