You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: simplifier.rs
    path of file: ./repos/prusti-dev/prusti-common/src/vir/optimizations/functions
    
    the code of the file until where you have to start completion: // Â© 2019, ETH Zurich
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 
    
    fn apply_rules(e: ast::Expr) -> ast::Expr {
        match e {
            ast::Expr::UnaryOp(ast::UnaryOp {
                op_kind: ast::UnaryOpKind::Not,
                argument:
                    box ast::Expr::Const(ast::ConstExpr {
                        value: ast::Const::Bool(b),
                        ..
                    }),
                position: pos,
            }) => ast::Expr::Const(ast::ConstExpr {
                value: ast::Const::Bool(!b),
                position: pos,
            }),
            ast::Expr::UnaryOp(ast::UnaryOp {
                op_kind: ast::UnaryOpKind::Not,
                argument:
                    box ast::Expr::BinOp(ast::BinOp {
                        op_kind: ast::BinaryOpKind::EqCmp,
                        box left,
                        box right,
                        ..
                    }),
                position: pos,
            }) => ast::Expr::BinOp(ast::BinOp {
                op_kind: ast::BinaryOpKind::NeCmp,
                left: Box::new(left),
                right: Box::new(right),
                position: pos,
            }),
            ast::Expr::BinOp(ast::BinOp {
                op_kind: ast::BinaryOpKind::And,
                left:
                    box ast::Expr::Const(ast::ConstExpr {
                        value: ast::Const::Bool(b1),
                        ..
                    }),
                right:
                    box ast::Expr::Const(ast::ConstExpr {
                        value: ast::Const::Bool(b2),
                        ..
                    }),
                position: pos,
            }) => ast::Expr::Const(ast::ConstExpr {
                value: ast::Const::Bool(b1 && b2),
                position: pos,
            }),
            ast::Expr::BinOp(ast::BinOp {
                op_kind: ast::BinaryOpKind::And,
                left:
                    box ast::Expr::Const(ast::ConstExpr {
                        value: ast::Const::Bool(b),
                        ..
                    }),
                right: box conjunct,
                ..
            })
            | ast::Expr::BinOp(ast::BinOp {
                op_kind: ast::BinaryOpKind::And,
                left: box conjunct,
                right:
                    box ast::Expr::Const(ast::ConstExpr {
                        value: ast::Const::Bool(b),
                        ..
                    }),
                ..
            }) => {
                if b {
                    conjunct
                } else {
                    false.into()
                }
            }
            ast::Expr::BinOp(ast::BinOp {
                op_kind: ast::BinaryOpKind::Or,
                left:
                    box ast::Expr::Const(ast::ConstExpr {
                        value: ast::Const::Bool(b),
                        ..
                    }),
                right: box disjunct,
                ..
            })
            | ast::Expr::BinOp(ast::BinOp {
                op_kind: ast::BinaryOpKind::Or,
                left: box disjunct,
                right:
                    box ast::Expr::Const(ast::ConstExpr {
                        value: ast::Const::Bool(b),
                        ..
                    }),
                ..
            }) => {
                if b {
                    true.into()
                } else {
                    disjunct
                }
            }
            ast::Expr::BinOp(ast::BinOp {
                op_kind: ast::BinaryOpKind::Implies,
                left: guard,
                right:
                    box ast::Expr::Const(ast::ConstExpr {
                        value: ast::Const::Bool(b),
                        ..
                    }),
                position: pos,
            }) => {
                if b {
                    true.into()
                } else {
                    ast::Expr::UnaryOp(ast::UnaryOp {
                        op_kind: ast::UnaryOpKind::Not,
                        argument: guard,
                        position: pos,
                    })
                }
            }
            ast::Expr::BinOp(ast::BinOp {
                op_kind: ast::BinaryOpKind::Implies,
                left:
                    box ast::Expr::Const(ast::ConstExpr {
                        value: ast::Const::Bool(b),
                        ..
                    }),
                right: box body,
                ..
            }) => {
                if b {
                    body
                } else {
                    true.into()
                }
            }
            ast::Expr::BinOp(ast::BinOp {
                op_kind: ast::BinaryOpKind::And,
                left: box op1,
                right: box op2,
                position: pos,
            }) => ast::Expr::BinOp(ast::BinOp {
                op_kind: ast::BinaryOpKind::And,
                left: Box::new(Self::apply_rules(op1)),
                right: Box::new(Self::apply_rules(op2)),
                position: pos,
            }),
            r => r,
        }
    }