<commit_before>pub mod surface;
pub mod surface_state;
pub mod sub_surface;
mod subsurface_manager;

pub use self::sub_surface::*;
use self::subsurface_manager::*;
pub use self::surface::*;
pub use self::surface_state::*;
<commit_msg>Flattened surface structure<commit_after>mod surface;
mod surface_state;
mod sub_surface;
mod subsurface_manager;

pub use self::sub_surface::*;
use self::subsurface_manager::*;
pub use self::surface::*;
pub use self::surface_state::*;
<|endoftext|>


<commit_before>//! Common types used by multiple graph implementations.

use std::ops;
use std::fmt::Debug;
use std::default::Default;
use std::hash::{Hash};

use num_traits::{NumCast,ToPrimitive};

use super::interface::{self, Id, Graph};
use super::iter::Indices;

// ================================================================
// Indices: types used to identify nodes and edges.

/// Default integer type used to identify nodes and edges.
pub type DefaultIndexType = u32;

/// Any integer type used as the underlying type for node and edge indices.
pub trait IndexType: Copy + Eq + Hash + Ord + Debug + NumCast + ToPrimitive + 'static {}
impl<T> IndexType for T where T: Copy + Eq + Hash + Ord + Debug + NumCast + ToPrimitive + 'static {}

macro_rules! impl_index_wrapper_type {
    ($tp: ty, $n: ident, $T: ident) => {
        impl<$T: IndexType> Id for $tp {
            #[inline(always)]
            fn new(v: usize) -> Self { $n(NumCast::from(v).unwrap()) }
            #[inline(always)]
            fn index(&self) -> usize { NumCast::from(self.0).unwrap() }
        }

        impl<U: NumCast + ToPrimitive, $T: IndexType> From<U> for $tp {
            fn from(v: U) -> Self {
                Self::new(NumCast::from(v).unwrap())
            }
        }
    }
}

/// Type used to identify and index the edges of a graph.
#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
pub struct EdgeIndex<T: IndexType>(T);
impl_index_wrapper_type!(EdgeIndex<T>,EdgeIndex,T);

/// Type used to identify and index the nodes of a graph.
#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
pub struct NodeIndex<T: IndexType>(T);
impl_index_wrapper_type!(NodeIndex<T>,NodeIndex,T);

// --------------------------------

/// Implement `interface::Node` for a type with members `incoming_edges` and
/// `outgoing_edges` of types compatible with `Vec<$I>`.
macro_rules! impl_basic_node {
    ($I: ident) => {
        //type EdgeIter<'a> = std::slice::Iter<'a,$I>;

        #[inline(always)]
        fn incoming_edges(&self) -> std::slice::Iter<$I> {
            self.incoming_edges.iter()
        }

        fn incoming_edge_count(&self) -> usize {
            self.incoming_edges.len()
        }

        #[inline(always)]
        fn outgoing_edges(&self) -> std::slice::Iter<$I> {
            self.outgoing_edges.iter()
        }

        fn outgoing_edge_count(&self) -> usize {
            self.outgoing_edges.len()
        }

        #[inline(always)]
        fn add_incoming_edge(&mut self, e: $I) {
            self.incoming_edges.push(e);
        }

        #[inline(always)]
        fn add_outgoing_edge(&mut self, e: $I) {
            self.outgoing_edges.push(e);
        }
    }
}

// --------------------------------
// AdjacencyList

/// Adjacency-list graph implementation.
#[derive(Clone,Debug)]
pub struct AdjacencyList<N, E> {
    nodes: Vec<N>,
    edges: Vec<E>
}

impl<N, E> AdjacencyList<N, E> {
    /// Create an empty AdjacencyList instance.
    pub fn new() -> Self {
        AdjacencyList{nodes: Vec::new(), edges: Vec::new()}
    }
}

impl<N, E> Default for AdjacencyList<N, E> {
    #[inline(always)]
    fn default() -> Self {
        AdjacencyList::new()
   }
}

impl<N, E> interface::Graph for AdjacencyList<N, E>
    where N: interface::Node,
          E: interface::Edge
{
    type NodeId = <E as interface::Edge>::NodeId;
    type EdgeId = <N as interface::Node>::EdgeId;
    type EdgeIdIterator = Indices<Self::EdgeId>;
    type NodeIdIterator = Indices<Self::NodeId>;

    #[inline(always)]
    fn contains_node(&self, n: Self::NodeId) -> bool {
        n.index() < self.nodes.len()
    }

    #[inline]
    fn node_ids(&self) -> Self::NodeIdIterator {
        Indices::new(0..self.nodes.len())
    }

    #[inline]
    fn node_count(&self) -> usize {
        self.nodes.len()
    }

    fn contains_edge(&self, e: Self::EdgeId) -> bool {
        e.index() < self.edges.len()
    }

    fn edge_ids(&self) -> Self::EdgeIdIterator {
        Indices::new(0..self.edges.len())
    }

    fn edge_count(&self) -> usize {
        self.edges.len()
    }

}

impl<N, E> interface::ConcreteGraph for AdjacencyList<N, E>
    where N: interface::DirectedNode,
          E: interface::DirectedEdge
{
    type Node = N;
    type Edge = E;

    #[inline(always)]
    fn node(&self, n: Self::NodeId) -> &Self::Node {
        &self.nodes[n.index()]
    }

    #[inline(always)]
    fn node_mut(&mut self, n: Self::NodeId) -> &mut Self::Node {
        &mut self.nodes[n.index()]
    }

    #[inline(always)]
    fn edge(&self, e: Self::EdgeId) -> &Self::Edge {
        &self.edges[e.index()]
    }

    #[inline(always)]
    fn edge_mut(&mut self, e: Self::EdgeId) -> &mut Self::Edge {
        &mut self.edges[e.index()]
    }

    #[inline(always)]
    fn add_node<T: Into<Self::Node>>(&mut self, n: T) -> Self::NodeId {
        self.nodes.push(n.into());
        Self::NodeId::new(self.nodes.len() - 1)
    }

    fn add_edge<T: Into<Self::Edge>>(&mut self, e: T) -> Self::EdgeId {
        let edge = e.into();
        let srcidx = edge.source().index();
        let destidx = edge.target().index();
        let node_count = self.node_count();
        panic_unless!(srcidx < node_count, "Invalid source-node index provided to `Graph::add_edge`");
        panic_unless!(destidx < node_count, "Invalid target-node index provided to `Graph::add_edge`");

        self.edges.push(edge);
        let index = Self::EdgeId::new(self.edges.len() - 1);

        // Update cross-referenced edge lists for the connected nodes.
        self.nodes[srcidx].add_outgoing_edge(index);
        self.nodes[destidx].add_incoming_edge(index);

        index
    }
}

// Implement node-data lookup via indexing.
macro_rules! graph_index_impl {
    ($tp: ty, $n: ident, $e: ident, $r: ident, $m: ident) => {
        impl<$n, $e, Ix> ops::Index<$tp> for AdjacencyList<N, E>
            where N: interface::Node,
                  E: interface::Edge,
                  Ix: IndexType {
            type Output = $r;
            fn index(&self, ix: $tp) -> &$r {
                &self.$m[ix.index()]
            }

        }
        impl<$n, $e, Ix> ops::IndexMut<$tp> for AdjacencyList<N, E>
            where N: interface::Node,
                  E: interface::Edge,
                  Ix: IndexType {
            fn index_mut(&mut self, ix: $tp) -> &mut $r {
                &mut self.$m[ix.index()]
            }

        }
    }
}
graph_index_impl!(EdgeIndex<Ix>, N, E, E, edges);
graph_index_impl!(NodeIndex<Ix>, N, E, N, nodes);
<commit_msg>util/graph/common: when adding an edge, use non-directed Edge API<commit_after>//! Common types used by multiple graph implementations.

use std::ops;
use std::fmt::Debug;
use std::default::Default;
use std::hash::{Hash};

use num_traits::{NumCast,ToPrimitive};

use super::interface::{self, Id, Graph};
use super::iter::Indices;

// ================================================================
// Indices: types used to identify nodes and edges.

/// Default integer type used to identify nodes and edges.
pub type DefaultIndexType = u32;

/// Any integer type used as the underlying type for node and edge indices.
pub trait IndexType: Copy + Eq + Hash + Ord + Debug + NumCast + ToPrimitive + 'static {}
impl<T> IndexType for T where T: Copy + Eq + Hash + Ord + Debug + NumCast + ToPrimitive + 'static {}

macro_rules! impl_index_wrapper_type {
    ($tp: ty, $n: ident, $T: ident) => {
        impl<$T: IndexType> Id for $tp {
            #[inline(always)]
            fn new(v: usize) -> Self { $n(NumCast::from(v).unwrap()) }
            #[inline(always)]
            fn index(&self) -> usize { NumCast::from(self.0).unwrap() }
        }

        impl<U: NumCast + ToPrimitive, $T: IndexType> From<U> for $tp {
            fn from(v: U) -> Self {
                Self::new(NumCast::from(v).unwrap())
            }
        }
    }
}

/// Type used to identify and index the edges of a graph.
#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
pub struct EdgeIndex<T: IndexType>(T);
impl_index_wrapper_type!(EdgeIndex<T>,EdgeIndex,T);

/// Type used to identify and index the nodes of a graph.
#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
pub struct NodeIndex<T: IndexType>(T);
impl_index_wrapper_type!(NodeIndex<T>,NodeIndex,T);

// --------------------------------

/// Implement `interface::Node` for a type with members `incoming_edges` and
/// `outgoing_edges` of types compatible with `Vec<$I>`.
macro_rules! impl_basic_node {
    ($I: ident) => {
        //type EdgeIter<'a> = std::slice::Iter<'a,$I>;

        #[inline(always)]
        fn incoming_edges(&self) -> std::slice::Iter<$I> {
            self.incoming_edges.iter()
        }

        fn incoming_edge_count(&self) -> usize {
            self.incoming_edges.len()
        }

        #[inline(always)]
        fn outgoing_edges(&self) -> std::slice::Iter<$I> {
            self.outgoing_edges.iter()
        }

        fn outgoing_edge_count(&self) -> usize {
            self.outgoing_edges.len()
        }

        #[inline(always)]
        fn add_incoming_edge(&mut self, e: $I) {
            self.incoming_edges.push(e);
        }

        #[inline(always)]
        fn add_outgoing_edge(&mut self, e: $I) {
            self.outgoing_edges.push(e);
        }
    }
}

// --------------------------------
// AdjacencyList

/// Adjacency-list graph implementation.
#[derive(Clone,Debug)]
pub struct AdjacencyList<N, E> {
    nodes: Vec<N>,
    edges: Vec<E>
}

impl<N, E> AdjacencyList<N, E> {
    /// Create an empty AdjacencyList instance.
    pub fn new() -> Self {
        AdjacencyList{nodes: Vec::new(), edges: Vec::new()}
    }
}

impl<N, E> Default for AdjacencyList<N, E> {
    #[inline(always)]
    fn default() -> Self {
        AdjacencyList::new()
   }
}

impl<N, E> interface::Graph for AdjacencyList<N, E>
    where N: interface::Node,
          E: interface::Edge
{
    type NodeId = <E as interface::Edge>::NodeId;
    type EdgeId = <N as interface::Node>::EdgeId;
    type EdgeIdIterator = Indices<Self::EdgeId>;
    type NodeIdIterator = Indices<Self::NodeId>;

    #[inline(always)]
    fn contains_node(&self, n: Self::NodeId) -> bool {
        n.index() < self.nodes.len()
    }

    #[inline]
    fn node_ids(&self) -> Self::NodeIdIterator {
        Indices::new(0..self.nodes.len())
    }

    #[inline]
    fn node_count(&self) -> usize {
        self.nodes.len()
    }

    fn contains_edge(&self, e: Self::EdgeId) -> bool {
        e.index() < self.edges.len()
    }

    fn edge_ids(&self) -> Self::EdgeIdIterator {
        Indices::new(0..self.edges.len())
    }

    fn edge_count(&self) -> usize {
        self.edges.len()
    }

}

impl<N, E> interface::ConcreteGraph for AdjacencyList<N, E>
    where N: interface::DirectedNode,
          E: interface::DirectedEdge
{
    type Node = N;
    type Edge = E;

    #[inline(always)]
    fn node(&self, n: Self::NodeId) -> &Self::Node {
        &self.nodes[n.index()]
    }

    #[inline(always)]
    fn node_mut(&mut self, n: Self::NodeId) -> &mut Self::Node {
        &mut self.nodes[n.index()]
    }

    #[inline(always)]
    fn edge(&self, e: Self::EdgeId) -> &Self::Edge {
        &self.edges[e.index()]
    }

    #[inline(always)]
    fn edge_mut(&mut self, e: Self::EdgeId) -> &mut Self::Edge {
        &mut self.edges[e.index()]
    }

    #[inline(always)]
    fn add_node<T: Into<Self::Node>>(&mut self, n: T) -> Self::NodeId {
        self.nodes.push(n.into());
        Self::NodeId::new(self.nodes.len() - 1)
    }

    fn add_edge<T: Into<Self::Edge>>(&mut self, e: T) -> Self::EdgeId {
        let edge = e.into();
        let (a, b) = edge.endpoints();
        let srcidx = a.index();
        let destidx = b.index();

        let node_count = self.node_count();
        panic_unless!(srcidx < node_count, "Invalid source-node index provided to `Graph::add_edge`");
        panic_unless!(destidx < node_count, "Invalid target-node index provided to `Graph::add_edge`");

        self.edges.push(edge);
        let index = Self::EdgeId::new(self.edges.len() - 1);

        // Update cross-referenced edge lists for the connected nodes.
        self.nodes[srcidx].add_outgoing_edge(index);
        self.nodes[destidx].add_incoming_edge(index);

        index
    }
}

// Implement node-data lookup via indexing.
macro_rules! graph_index_impl {
    ($tp: ty, $n: ident, $e: ident, $r: ident, $m: ident) => {
        impl<$n, $e, Ix> ops::Index<$tp> for AdjacencyList<N, E>
            where N: interface::Node,
                  E: interface::Edge,
                  Ix: IndexType {
            type Output = $r;
            fn index(&self, ix: $tp) -> &$r {
                &self.$m[ix.index()]
            }

        }
        impl<$n, $e, Ix> ops::IndexMut<$tp> for AdjacencyList<N, E>
            where N: interface::Node,
                  E: interface::Edge,
                  Ix: IndexType {
            fn index_mut(&mut self, ix: $tp) -> &mut $r {
                &mut self.$m[ix.index()]
            }

        }
    }
}
graph_index_impl!(EdgeIndex<Ix>, N, E, E, edges);
graph_index_impl!(NodeIndex<Ix>, N, E, N, nodes);
<|endoftext|>


<commit_before>use if_chain::if_chain;
use rustc::hir;
use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;

use crate::utils::{
    get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, trait_ref_of_method, SpanlessEq,
};
use crate::utils::{higher, sugg};

declare_clippy_lint! {
    /// **What it does:** Checks for `a = a op b` or `a = b commutative_op a`
    /// patterns.
    ///
    /// **Why is this bad?** These can be written as the shorter `a op= b`.
    ///
    /// **Known problems:** While forbidden by the spec, `OpAssign` traits may have
    /// implementations that differ from the regular `Op` impl.
    ///
    /// **Example:**
    /// ```rust
    /// let mut a = 5;
    /// let b = 0;
    /// // ...
    /// a = a + b;
    /// ```
    pub ASSIGN_OP_PATTERN,
    style,
    "assigning the result of an operation on a variable to that same variable"
}

declare_clippy_lint! {
    /// **What it does:** Checks for `a op= a op b` or `a op= b op a` patterns.
    ///
    /// **Why is this bad?** Most likely these are bugs where one meant to write `a
    /// op= b`.
    ///
    /// **Known problems:** Clippy cannot know for sure if `a op= a op b` should have
    /// been `a = a op a op b` or `a = a op b`/`a op= b`. Therefore, it suggests both.
    /// If `a op= a op b` is really the correct behaviour it should be
    /// written as `a = a op a op b` as it's less confusing.
    ///
    /// **Example:**
    /// ```rust
    /// let mut a = 5;
    /// let b = 2;
    /// // ...
    /// a += a + b;
    /// ```
    pub MISREFACTORED_ASSIGN_OP,
    complexity,
    "having a variable on both sides of an assign op"
}

declare_lint_pass!(AssignOps => [ASSIGN_OP_PATTERN, MISREFACTORED_ASSIGN_OP]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
    #[allow(clippy::too_many_lines)]
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
        match &expr.node {
            hir::ExprKind::AssignOp(op, lhs, rhs) => {
                if let hir::ExprKind::Binary(binop, l, r) = &rhs.node {
                    if op.node != binop.node {
                        return;
                    }
                    // lhs op= l op r
                    if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, l) {
                        lint_misrefactored_assign_op(cx, expr, *op, rhs, lhs, r);
                    }
                    // lhs op= l commutative_op r
                    if is_commutative(op.node) && SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, r) {
                        lint_misrefactored_assign_op(cx, expr, *op, rhs, lhs, l);
                    }
                }
            },
            hir::ExprKind::Assign(assignee, e) => {
                if let hir::ExprKind::Binary(op, l, r) = &e.node {
                    #[allow(clippy::cognitive_complexity)]
                    let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
                        let ty = cx.tables.expr_ty(assignee);
                        let rty = cx.tables.expr_ty(rhs);
                        macro_rules! ops {
                            ($op:expr,
                             $cx:expr,
                             $ty:expr,
                             $rty:expr,
                             $($trait_name:ident),+) => {
                                match $op {
                                    $(hir::BinOpKind::$trait_name => {
                                        let [krate, module] = crate::utils::paths::OPS_MODULE;
                                        let path: [&str; 3] = [krate, module, concat!(stringify!($trait_name), "Assign")];
                                        let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) {
                                            trait_id
                                        } else {
                                            return; // useless if the trait doesn't exist
                                        };
                                        // check that we are not inside an `impl AssignOp` of this exact operation
                                        let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id);
                                        if_chain! {
                                            if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn);
                                            if trait_ref.path.res.def_id() == trait_id;
                                            then { return; }
                                        }
                                        implements_trait($cx, $ty, trait_id, &[$rty])
                                    },)*
                                    _ => false,
                                }
                            }
                        }
                        if ops!(
                            op.node,
                            cx,
                            ty,
                            rty.into(),
                            Add,
                            Sub,
                            Mul,
                            Div,
                            Rem,
                            And,
                            Or,
                            BitAnd,
                            BitOr,
                            BitXor,
                            Shr,
                            Shl
                        ) {
                            span_lint_and_then(
                                cx,
                                ASSIGN_OP_PATTERN,
                                expr.span,
                                "manual implementation of an assign operation",
                                |db| {
                                    if let (Some(snip_a), Some(snip_r)) =
                                        (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span))
                                    {
                                        db.span_suggestion(
                                            expr.span,
                                            "replace it with",
                                            format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
                                            Applicability::MachineApplicable,
                                        );
                                    }
                                },
                            );
                        }
                    };

                    let mut visitor = ExprVisitor {
                        assignee,
                        counter: 0,
                        cx,
                    };

                    walk_expr(&mut visitor, e);

                    if visitor.counter == 1 {
                        // a = a op b
                        if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, l) {
                            lint(assignee, r);
                        }
                        // a = b commutative_op a
                        // Limited to primitive type as these ops are know to be commutative
                        if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r)
                            && cx.tables.expr_ty(assignee).is_primitive_ty()
                        {
                            match op.node {
                                hir::BinOpKind::Add
                                | hir::BinOpKind::Mul
                                | hir::BinOpKind::And
                                | hir::BinOpKind::Or
                                | hir::BinOpKind::BitXor
                                | hir::BinOpKind::BitAnd
                                | hir::BinOpKind::BitOr => {
                                    lint(assignee, l);
                                },
                                _ => {},
                            }
                        }
                    }
                }
            },
            _ => {},
        }
    }
}

fn lint_misrefactored_assign_op(
    cx: &LateContext<'_, '_>,
    expr: &hir::Expr,
    op: hir::BinOp,
    rhs: &hir::Expr,
    assignee: &hir::Expr,
    rhs_other: &hir::Expr,
) {
    span_lint_and_then(
        cx,
        MISREFACTORED_ASSIGN_OP,
        expr.span,
        "variable appears on both sides of an assignment operation",
        |db| {
            if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) {
                let a = &sugg::Sugg::hir(cx, assignee, "..");
                let r = &sugg::Sugg::hir(cx, rhs, "..");
                let long = format!("{} = {}", snip_a, sugg::make_binop(higher::binop(op.node), a, r));
                db.span_suggestion(
                    expr.span,
                    &format!(
                        "Did you mean {} = {} {} {} or {}? Consider replacing it with",
                        snip_a,
                        snip_a,
                        op.node.as_str(),
                        snip_r,
                        long
                    ),
                    format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
                    Applicability::MachineApplicable,
                );
                db.span_suggestion(
                    expr.span,
                    "or",
                    long,
                    Applicability::MachineApplicable, // snippet
                );
            }
        },
    );
}

fn is_commutative(op: hir::BinOpKind) -> bool {
    use rustc::hir::BinOpKind::*;
    match op {
        Add | Mul | And | Or | BitXor | BitAnd | BitOr | Eq | Ne => true,
        Sub | Div | Rem | Shl | Shr | Lt | Le | Ge | Gt => false,
    }
}

struct ExprVisitor<'a, 'tcx> {
    assignee: &'a hir::Expr,
    counter: u8,
    cx: &'a LateContext<'a, 'tcx>,
}

impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> {
    fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
        if SpanlessEq::new(self.cx).ignore_fn().eq_expr(self.assignee, expr) {
            self.counter += 1;
        }

        walk_expr(self, expr);
    }
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::None
    }
}
<commit_msg>assign_ops: Remove MachineApplicable<commit_after>use if_chain::if_chain;
use rustc::hir;
use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;

use crate::utils::{
    get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, trait_ref_of_method, SpanlessEq,
};
use crate::utils::{higher, sugg};

declare_clippy_lint! {
    /// **What it does:** Checks for `a = a op b` or `a = b commutative_op a`
    /// patterns.
    ///
    /// **Why is this bad?** These can be written as the shorter `a op= b`.
    ///
    /// **Known problems:** While forbidden by the spec, `OpAssign` traits may have
    /// implementations that differ from the regular `Op` impl.
    ///
    /// **Example:**
    /// ```rust
    /// let mut a = 5;
    /// let b = 0;
    /// // ...
    /// a = a + b;
    /// ```
    pub ASSIGN_OP_PATTERN,
    style,
    "assigning the result of an operation on a variable to that same variable"
}

declare_clippy_lint! {
    /// **What it does:** Checks for `a op= a op b` or `a op= b op a` patterns.
    ///
    /// **Why is this bad?** Most likely these are bugs where one meant to write `a
    /// op= b`.
    ///
    /// **Known problems:** Clippy cannot know for sure if `a op= a op b` should have
    /// been `a = a op a op b` or `a = a op b`/`a op= b`. Therefore, it suggests both.
    /// If `a op= a op b` is really the correct behaviour it should be
    /// written as `a = a op a op b` as it's less confusing.
    ///
    /// **Example:**
    /// ```rust
    /// let mut a = 5;
    /// let b = 2;
    /// // ...
    /// a += a + b;
    /// ```
    pub MISREFACTORED_ASSIGN_OP,
    complexity,
    "having a variable on both sides of an assign op"
}

declare_lint_pass!(AssignOps => [ASSIGN_OP_PATTERN, MISREFACTORED_ASSIGN_OP]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
    #[allow(clippy::too_many_lines)]
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
        match &expr.node {
            hir::ExprKind::AssignOp(op, lhs, rhs) => {
                if let hir::ExprKind::Binary(binop, l, r) = &rhs.node {
                    if op.node != binop.node {
                        return;
                    }
                    // lhs op= l op r
                    if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, l) {
                        lint_misrefactored_assign_op(cx, expr, *op, rhs, lhs, r);
                    }
                    // lhs op= l commutative_op r
                    if is_commutative(op.node) && SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, r) {
                        lint_misrefactored_assign_op(cx, expr, *op, rhs, lhs, l);
                    }
                }
            },
            hir::ExprKind::Assign(assignee, e) => {
                if let hir::ExprKind::Binary(op, l, r) = &e.node {
                    #[allow(clippy::cognitive_complexity)]
                    let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
                        let ty = cx.tables.expr_ty(assignee);
                        let rty = cx.tables.expr_ty(rhs);
                        macro_rules! ops {
                            ($op:expr,
                             $cx:expr,
                             $ty:expr,
                             $rty:expr,
                             $($trait_name:ident),+) => {
                                match $op {
                                    $(hir::BinOpKind::$trait_name => {
                                        let [krate, module] = crate::utils::paths::OPS_MODULE;
                                        let path: [&str; 3] = [krate, module, concat!(stringify!($trait_name), "Assign")];
                                        let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) {
                                            trait_id
                                        } else {
                                            return; // useless if the trait doesn't exist
                                        };
                                        // check that we are not inside an `impl AssignOp` of this exact operation
                                        let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id);
                                        if_chain! {
                                            if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn);
                                            if trait_ref.path.res.def_id() == trait_id;
                                            then { return; }
                                        }
                                        implements_trait($cx, $ty, trait_id, &[$rty])
                                    },)*
                                    _ => false,
                                }
                            }
                        }
                        if ops!(
                            op.node,
                            cx,
                            ty,
                            rty.into(),
                            Add,
                            Sub,
                            Mul,
                            Div,
                            Rem,
                            And,
                            Or,
                            BitAnd,
                            BitOr,
                            BitXor,
                            Shr,
                            Shl
                        ) {
                            span_lint_and_then(
                                cx,
                                ASSIGN_OP_PATTERN,
                                expr.span,
                                "manual implementation of an assign operation",
                                |db| {
                                    if let (Some(snip_a), Some(snip_r)) =
                                        (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span))
                                    {
                                        db.span_suggestion(
                                            expr.span,
                                            "replace it with",
                                            format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
                                            Applicability::MachineApplicable,
                                        );
                                    }
                                },
                            );
                        }
                    };

                    let mut visitor = ExprVisitor {
                        assignee,
                        counter: 0,
                        cx,
                    };

                    walk_expr(&mut visitor, e);

                    if visitor.counter == 1 {
                        // a = a op b
                        if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, l) {
                            lint(assignee, r);
                        }
                        // a = b commutative_op a
                        // Limited to primitive type as these ops are know to be commutative
                        if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r)
                            && cx.tables.expr_ty(assignee).is_primitive_ty()
                        {
                            match op.node {
                                hir::BinOpKind::Add
                                | hir::BinOpKind::Mul
                                | hir::BinOpKind::And
                                | hir::BinOpKind::Or
                                | hir::BinOpKind::BitXor
                                | hir::BinOpKind::BitAnd
                                | hir::BinOpKind::BitOr => {
                                    lint(assignee, l);
                                },
                                _ => {},
                            }
                        }
                    }
                }
            },
            _ => {},
        }
    }
}

fn lint_misrefactored_assign_op(
    cx: &LateContext<'_, '_>,
    expr: &hir::Expr,
    op: hir::BinOp,
    rhs: &hir::Expr,
    assignee: &hir::Expr,
    rhs_other: &hir::Expr,
) {
    span_lint_and_then(
        cx,
        MISREFACTORED_ASSIGN_OP,
        expr.span,
        "variable appears on both sides of an assignment operation",
        |db| {
            if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) {
                let a = &sugg::Sugg::hir(cx, assignee, "..");
                let r = &sugg::Sugg::hir(cx, rhs, "..");
                let long = format!("{} = {}", snip_a, sugg::make_binop(higher::binop(op.node), a, r));
                db.span_suggestion(
                    expr.span,
                    &format!(
                        "Did you mean {} = {} {} {} or {}? Consider replacing it with",
                        snip_a,
                        snip_a,
                        op.node.as_str(),
                        snip_r,
                        long
                    ),
                    format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
                    Applicability::MaybeIncorrect,
                );
                db.span_suggestion(
                    expr.span,
                    "or",
                    long,
                    Applicability::MaybeIncorrect, // snippet
                );
            }
        },
    );
}

fn is_commutative(op: hir::BinOpKind) -> bool {
    use rustc::hir::BinOpKind::*;
    match op {
        Add | Mul | And | Or | BitXor | BitAnd | BitOr | Eq | Ne => true,
        Sub | Div | Rem | Shl | Shr | Lt | Le | Ge | Gt => false,
    }
}

struct ExprVisitor<'a, 'tcx> {
    assignee: &'a hir::Expr,
    counter: u8,
    cx: &'a LateContext<'a, 'tcx>,
}

impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> {
    fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
        if SpanlessEq::new(self.cx).ignore_fn().eq_expr(self.assignee, expr) {
            self.counter += 1;
        }

        walk_expr(self, expr);
    }
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::None
    }
}
<|endoftext|>


<commit_before>use rustc::hir;
use rustc::lint::*;
use syntax::ast;
use utils::{span_lint_and_then, snippet_opt, SpanlessEq, get_trait_def_id, implements_trait};
use utils::{higher, sugg};

/// **What it does:** Checks for compound assignment operations (`+=` and similar).
///
/// **Why is this bad?** Projects with many developers from languages without
/// those operations may find them unreadable and not worth their weight.
///
/// **Known problems:** Types implementing `OpAssign` don't necessarily implement `Op`.
///
/// **Example:**
/// ```rust
/// a += 1;
/// ```
declare_restriction_lint! {
    pub ASSIGN_OPS,
    "any compound assignment operation"
}

/// **What it does:** Checks for `a = a op b` or `a = b commutative_op a` patterns.
///
/// **Why is this bad?** These can be written as the shorter `a op= b`.
///
/// **Known problems:** While forbidden by the spec, `OpAssign` traits may have
/// implementations that differ from the regular `Op` impl.
///
/// **Example:**
/// ```rust
/// let mut a = 5;
/// ...
/// a = a + b;
/// ```
declare_lint! {
    pub ASSIGN_OP_PATTERN,
    Warn,
    "assigning the result of an operation on a variable to that same variable"
}

/// **What it does:** Checks for `a op= a op b` or `a op= b op a` patterns.
///
/// **Why is this bad?** Most likely these are bugs where one meant to write `a op= b`.
///
/// **Known problems:** Someone might actually mean `a op= a op b`, but that
/// should rather be written as `a = (2 * a) op b` where applicable.
///
/// **Example:**
/// ```rust
/// let mut a = 5;
/// ...
/// a += a + b;
/// ```
declare_lint! {
    pub MISREFACTORED_ASSIGN_OP,
    Warn,
    "having a variable on both sides of an assign op"
}

#[derive(Copy, Clone, Default)]
pub struct AssignOps;

impl LintPass for AssignOps {
    fn get_lints(&self) -> LintArray {
        lint_array!(ASSIGN_OPS, ASSIGN_OP_PATTERN, MISREFACTORED_ASSIGN_OP)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
        match expr.node {
            hir::ExprAssignOp(op, ref lhs, ref rhs) => {
                span_lint_and_then(cx, ASSIGN_OPS, expr.span, "assign operation detected", |db| {
                    let lhs = &sugg::Sugg::hir(cx, lhs, "..");
                    let rhs = &sugg::Sugg::hir(cx, rhs, "..");

                    db.span_suggestion(expr.span,
                                       "replace it with",
                                       format!("{} = {}", lhs, sugg::make_binop(higher::binop(op.node), lhs, rhs)));
                });
                if let hir::ExprBinary(binop, ref l, ref r) = rhs.node {
                    if op.node == binop.node {
                        let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
                            let ty = cx.tables.expr_ty(assignee);
                            if ty.walk_shallow().next().is_some() {
                                return; // implements_trait does not work with generics
                            }
                            let rty = cx.tables.expr_ty(rhs);
                            if rty.walk_shallow().next().is_some() {
                                return; // implements_trait does not work with generics
                            }
                            span_lint_and_then(cx,
                                               MISREFACTORED_ASSIGN_OP,
                                               expr.span,
                                               "variable appears on both sides of an assignment operation",
                                               |db| if let (Some(snip_a), Some(snip_r)) =
                                                   (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) {
                                                   db.span_suggestion(expr.span,
                                                       "replace it with",
                                                       format!("{} {}= {}", snip_a, op.node.as_str(), snip_r));
                                               });
                        };
                        // lhs op= l op r
                        if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, l) {
                            lint(lhs, r);
                        }
                        // lhs op= l commutative_op r
                        if is_commutative(op.node) && SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, r) {
                            lint(lhs, l);
                        }
                    }
                }
            },
            hir::ExprAssign(ref assignee, ref e) => {
                if let hir::ExprBinary(op, ref l, ref r) = e.node {
                    #[allow(cyclomatic_complexity)]
                    let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
                        let ty = cx.tables.expr_ty(assignee);
                        if ty.walk_shallow().next().is_some() {
                            return; // implements_trait does not work with generics
                        }
                        let rty = cx.tables.expr_ty(rhs);
                        if rty.walk_shallow().next().is_some() {
                            return; // implements_trait does not work with generics
                        }
                        macro_rules! ops {
                            ($op:expr,
                             $cx:expr,
                             $ty:expr,
                             $rty:expr,
                             $($trait_name:ident:$full_trait_name:ident),+) => {
                                match $op {
                                    $(hir::$full_trait_name => {
                                        let [krate, module] = ::utils::paths::OPS_MODULE;
                                        let path = [krate, module, concat!(stringify!($trait_name), "Assign")];
                                        let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) {
                                            trait_id
                                        } else {
                                            return; // useless if the trait doesn't exist
                                        };
                                        // check that we are not inside an `impl AssignOp` of this exact operation
                                        let parent_fn = cx.tcx.map.get_parent(e.id);
                                        let parent_impl = cx.tcx.map.get_parent(parent_fn);
                                        // the crate node is the only one that is not in the map
                                        if_let_chain!{[
                                            parent_impl != ast::CRATE_NODE_ID,
                                            let hir::map::Node::NodeItem(item) = cx.tcx.map.get(parent_impl),
                                            let hir::Item_::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node,
                                            trait_ref.path.def.def_id() == trait_id
                                        ], { return; }}
                                        implements_trait($cx, $ty, trait_id, vec![$rty])
                                    },)*
                                    _ => false,
                                }
                            }
                        }
                        if ops!(op.node,
                                cx,
                                ty,
                                rty,
                                Add: BiAdd,
                                Sub: BiSub,
                                Mul: BiMul,
                                Div: BiDiv,
                                Rem: BiRem,
                                And: BiAnd,
                                Or: BiOr,
                                BitAnd: BiBitAnd,
                                BitOr: BiBitOr,
                                BitXor: BiBitXor,
                                Shr: BiShr,
                                Shl: BiShl) {
                            span_lint_and_then(cx,
                                               ASSIGN_OP_PATTERN,
                                               expr.span,
                                               "manual implementation of an assign operation",
                                               |db| if let (Some(snip_a), Some(snip_r)) =
                                                   (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) {
                                                   db.span_suggestion(expr.span,
                                                       "replace it with",
                                                       format!("{} {}= {}", snip_a, op.node.as_str(), snip_r));
                                               });
                        }
                    };
                    // a = a op b
                    if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, l) {
                        lint(assignee, r);
                    }
                    // a = b commutative_op a
                    if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) {
                        match op.node {
                            hir::BiAdd | hir::BiMul | hir::BiAnd | hir::BiOr | hir::BiBitXor | hir::BiBitAnd |
                            hir::BiBitOr => {
                                lint(assignee, l);
                            },
                            _ => {},
                        }
                    }
                }
            },
            _ => {},
        }
    }
}

fn is_commutative(op: hir::BinOp_) -> bool {
    use rustc::hir::BinOp_::*;
    match op {
        BiAdd | BiMul | BiAnd | BiOr | BiBitXor | BiBitAnd | BiBitOr | BiEq | BiNe => true,
        BiSub | BiDiv | BiRem | BiShl | BiShr | BiLt | BiLe | BiGe | BiGt => false,
    }
}
<commit_msg>Fix rustfmt<commit_after>use rustc::hir;
use rustc::lint::*;
use syntax::ast;
use utils::{span_lint_and_then, snippet_opt, SpanlessEq, get_trait_def_id, implements_trait};
use utils::{higher, sugg};

/// **What it does:** Checks for compound assignment operations (`+=` and similar).
///
/// **Why is this bad?** Projects with many developers from languages without
/// those operations may find them unreadable and not worth their weight.
///
/// **Known problems:** Types implementing `OpAssign` don't necessarily implement `Op`.
///
/// **Example:**
/// ```rust
/// a += 1;
/// ```
declare_restriction_lint! {
    pub ASSIGN_OPS,
    "any compound assignment operation"
}

/// **What it does:** Checks for `a = a op b` or `a = b commutative_op a` patterns.
///
/// **Why is this bad?** These can be written as the shorter `a op= b`.
///
/// **Known problems:** While forbidden by the spec, `OpAssign` traits may have
/// implementations that differ from the regular `Op` impl.
///
/// **Example:**
/// ```rust
/// let mut a = 5;
/// ...
/// a = a + b;
/// ```
declare_lint! {
    pub ASSIGN_OP_PATTERN,
    Warn,
    "assigning the result of an operation on a variable to that same variable"
}

/// **What it does:** Checks for `a op= a op b` or `a op= b op a` patterns.
///
/// **Why is this bad?** Most likely these are bugs where one meant to write `a op= b`.
///
/// **Known problems:** Someone might actually mean `a op= a op b`, but that
/// should rather be written as `a = (2 * a) op b` where applicable.
///
/// **Example:**
/// ```rust
/// let mut a = 5;
/// ...
/// a += a + b;
/// ```
declare_lint! {
    pub MISREFACTORED_ASSIGN_OP,
    Warn,
    "having a variable on both sides of an assign op"
}

#[derive(Copy, Clone, Default)]
pub struct AssignOps;

impl LintPass for AssignOps {
    fn get_lints(&self) -> LintArray {
        lint_array!(ASSIGN_OPS, ASSIGN_OP_PATTERN, MISREFACTORED_ASSIGN_OP)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
        match expr.node {
            hir::ExprAssignOp(op, ref lhs, ref rhs) => {
                span_lint_and_then(cx, ASSIGN_OPS, expr.span, "assign operation detected", |db| {
                    let lhs = &sugg::Sugg::hir(cx, lhs, "..");
                    let rhs = &sugg::Sugg::hir(cx, rhs, "..");

                    db.span_suggestion(expr.span,
                                       "replace it with",
                                       format!("{} = {}", lhs, sugg::make_binop(higher::binop(op.node), lhs, rhs)));
                });
                if let hir::ExprBinary(binop, ref l, ref r) = rhs.node {
                    if op.node == binop.node {
                        let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
                            let ty = cx.tables.expr_ty(assignee);
                            if ty.walk_shallow().next().is_some() {
                                return; // implements_trait does not work with generics
                            }
                            let rty = cx.tables.expr_ty(rhs);
                            if rty.walk_shallow().next().is_some() {
                                return; // implements_trait does not work with generics
                            }
                            span_lint_and_then(cx,
                                               MISREFACTORED_ASSIGN_OP,
                                               expr.span,
                                               "variable appears on both sides of an assignment operation",
                                               |db| if let (Some(snip_a), Some(snip_r)) =
                                                   (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) {
                                                   db.span_suggestion(expr.span,
                                                                      "replace it with",
                                                                      format!("{} {}= {}",
                                                                              snip_a,
                                                                              op.node.as_str(),
                                                                              snip_r));
                                               });
                        };
                        // lhs op= l op r
                        if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, l) {
                            lint(lhs, r);
                        }
                        // lhs op= l commutative_op r
                        if is_commutative(op.node) && SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, r) {
                            lint(lhs, l);
                        }
                    }
                }
            },
            hir::ExprAssign(ref assignee, ref e) => {
                if let hir::ExprBinary(op, ref l, ref r) = e.node {
                    #[allow(cyclomatic_complexity)]
                    let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
                        let ty = cx.tables.expr_ty(assignee);
                        if ty.walk_shallow().next().is_some() {
                            return; // implements_trait does not work with generics
                        }
                        let rty = cx.tables.expr_ty(rhs);
                        if rty.walk_shallow().next().is_some() {
                            return; // implements_trait does not work with generics
                        }
                        macro_rules! ops {
                            ($op:expr,
                             $cx:expr,
                             $ty:expr,
                             $rty:expr,
                             $($trait_name:ident:$full_trait_name:ident),+) => {
                                match $op {
                                    $(hir::$full_trait_name => {
                                        let [krate, module] = ::utils::paths::OPS_MODULE;
                                        let path = [krate, module, concat!(stringify!($trait_name), "Assign")];
                                        let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) {
                                            trait_id
                                        } else {
                                            return; // useless if the trait doesn't exist
                                        };
                                        // check that we are not inside an `impl AssignOp` of this exact operation
                                        let parent_fn = cx.tcx.map.get_parent(e.id);
                                        let parent_impl = cx.tcx.map.get_parent(parent_fn);
                                        // the crate node is the only one that is not in the map
                                        if_let_chain!{[
                                            parent_impl != ast::CRATE_NODE_ID,
                                            let hir::map::Node::NodeItem(item) = cx.tcx.map.get(parent_impl),
                                            let hir::Item_::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node,
                                            trait_ref.path.def.def_id() == trait_id
                                        ], { return; }}
                                        implements_trait($cx, $ty, trait_id, vec![$rty])
                                    },)*
                                    _ => false,
                                }
                            }
                        }
                        if ops!(op.node,
                                cx,
                                ty,
                                rty,
                                Add: BiAdd,
                                Sub: BiSub,
                                Mul: BiMul,
                                Div: BiDiv,
                                Rem: BiRem,
                                And: BiAnd,
                                Or: BiOr,
                                BitAnd: BiBitAnd,
                                BitOr: BiBitOr,
                                BitXor: BiBitXor,
                                Shr: BiShr,
                                Shl: BiShl) {
                            span_lint_and_then(cx,
                                               ASSIGN_OP_PATTERN,
                                               expr.span,
                                               "manual implementation of an assign operation",
                                               |db| if let (Some(snip_a), Some(snip_r)) =
                                                   (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) {
                                                   db.span_suggestion(expr.span,
                                                                      "replace it with",
                                                                      format!("{} {}= {}",
                                                                              snip_a,
                                                                              op.node.as_str(),
                                                                              snip_r));
                                               });
                        }
                    };
                    // a = a op b
                    if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, l) {
                        lint(assignee, r);
                    }
                    // a = b commutative_op a
                    if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) {
                        match op.node {
                            hir::BiAdd | hir::BiMul | hir::BiAnd | hir::BiOr | hir::BiBitXor | hir::BiBitAnd |
                            hir::BiBitOr => {
                                lint(assignee, l);
                            },
                            _ => {},
                        }
                    }
                }
            },
            _ => {},
        }
    }
}

fn is_commutative(op: hir::BinOp_) -> bool {
    use rustc::hir::BinOp_::*;
    match op {
        BiAdd | BiMul | BiAnd | BiOr | BiBitXor | BiBitAnd | BiBitOr | BiEq | BiNe => true,
        BiSub | BiDiv | BiRem | BiShl | BiShr | BiLt | BiLe | BiGe | BiGt => false,
    }
}
<|endoftext|>


<commit_before>use core::fmt;
use core::pin::Pin;
use futures_core::future::Future;
use futures_core::stream::{FusedStream, Stream};
use futures_core::task::{Context, Poll};
use pin_utils::{unsafe_pinned, unsafe_unpinned};

/// Creates a `Stream` from a seed and a closure returning a `Future`.
///
/// This function is the dual for the `Stream::fold()` adapter: while
/// `Stream::fold()` reduces a `Stream` to one single value, `unfold()` creates a
/// `Stream` from a seed value.
///
/// `unfold()` will call the provided closure with the provided seed, then wait
/// for the returned `Future` to complete with `(a, b)`. It will then yield the
/// value `a`, and use `b` as the next internal state.
///
/// If the closure returns `None` instead of `Some(Future)`, then the `unfold()`
/// will stop producing items and return `Poll::Ready(None)` in future
/// calls to `poll()`.
///
/// This function can typically be used when wanting to go from the "world of
/// futures" to the "world of streams": the provided closure can build a
/// `Future` using other library functions working on futures, and `unfold()`
/// will turn it into a `Stream` by repeating the operation.
///
/// # Example
///
/// ```
/// # futures::executor::block_on(async {
/// use futures::stream::{self, StreamExt};
///
/// let stream = stream::unfold(0, |state| async move {
///     if state <= 2 {
///         let next_state = state + 1;
///         let yielded = state  * 2;
///         Some((yielded, next_state))
///     } else {
///         None
///     }
/// });
///
/// let result = stream.collect::<Vec<i32>>().await;
/// assert_eq!(result, vec![0, 2, 4]);
/// # });
/// ```
pub fn unfold<T, F, Fut, Item>(init: T, f: F) -> Unfold<T, F, Fut>
    where F: FnMut(T) -> Fut,
          Fut: Future<Output = Option<(Item, T)>>,
{
    Unfold {
        f,
        state: Some(init),
        fut: None,
    }
}

/// Stream for the [`unfold`] function.
#[must_use = "streams do nothing unless polled"]
pub struct Unfold<T, F, Fut> {
    f: F,
    state: Option<T>,
    fut: Option<Fut>,
}

impl<T, F, Fut: Unpin> Unpin for Unfold<T, F, Fut> {}

impl<T, F, Fut> fmt::Debug for Unfold<T, F, Fut>
where
    T: fmt::Debug,
    Fut: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Unfold")
            .field("state", &self.state)
            .field("fut", &self.fut)
            .finish()
    }
}

impl<T, F, Fut> Unfold<T, F, Fut> {
    unsafe_unpinned!(f: F);
    unsafe_unpinned!(state: Option<T>);
    unsafe_pinned!(fut: Option<Fut>);
}

impl<T, F, Fut, Item> FusedStream for Unfold<T, F, Fut>
    where F: FnMut(T) -> Fut,
          Fut: Future<Output = Option<(Item, T)>>,
{
    fn is_terminated(&self) -> bool {
        self.state.is_none() && self.fut.is_none()
    }
}

impl<T, F, Fut, Item> Stream for Unfold<T, F, Fut>
    where F: FnMut(T) -> Fut,
          Fut: Future<Output = Option<(Item, T)>>,
{
    type Item = Item;

    fn poll_next(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Self::Item>> {
        if let Some(state) = self.as_mut().state().take() {
            let fut = (self.as_mut().f())(state);
            self.as_mut().fut().set(Some(fut));
        }

        let step = ready!(self.as_mut().fut().as_pin_mut().unwrap().poll(cx));
        self.as_mut().fut().set(None);

        if let Some((item, next_state)) = step {
            *self.as_mut().state() = Some(next_state);
            Poll::Ready(Some(item))
        } else {
            Poll::Ready(None)
        }
    }
}
<commit_msg>stream::unfold: Better panic message<commit_after>use core::fmt;
use core::pin::Pin;
use futures_core::future::Future;
use futures_core::stream::{FusedStream, Stream};
use futures_core::task::{Context, Poll};
use pin_utils::{unsafe_pinned, unsafe_unpinned};

/// Creates a `Stream` from a seed and a closure returning a `Future`.
///
/// This function is the dual for the `Stream::fold()` adapter: while
/// `Stream::fold()` reduces a `Stream` to one single value, `unfold()` creates a
/// `Stream` from a seed value.
///
/// `unfold()` will call the provided closure with the provided seed, then wait
/// for the returned `Future` to complete with `(a, b)`. It will then yield the
/// value `a`, and use `b` as the next internal state.
///
/// If the closure returns `None` instead of `Some(Future)`, then the `unfold()`
/// will stop producing items and return `Poll::Ready(None)` in future
/// calls to `poll()`.
///
/// This function can typically be used when wanting to go from the "world of
/// futures" to the "world of streams": the provided closure can build a
/// `Future` using other library functions working on futures, and `unfold()`
/// will turn it into a `Stream` by repeating the operation.
///
/// # Example
///
/// ```
/// # futures::executor::block_on(async {
/// use futures::stream::{self, StreamExt};
///
/// let stream = stream::unfold(0, |state| async move {
///     if state <= 2 {
///         let next_state = state + 1;
///         let yielded = state  * 2;
///         Some((yielded, next_state))
///     } else {
///         None
///     }
/// });
///
/// let result = stream.collect::<Vec<i32>>().await;
/// assert_eq!(result, vec![0, 2, 4]);
/// # });
/// ```
pub fn unfold<T, F, Fut, Item>(init: T, f: F) -> Unfold<T, F, Fut>
    where F: FnMut(T) -> Fut,
          Fut: Future<Output = Option<(Item, T)>>,
{
    Unfold {
        f,
        state: Some(init),
        fut: None,
    }
}

/// Stream for the [`unfold`] function.
#[must_use = "streams do nothing unless polled"]
pub struct Unfold<T, F, Fut> {
    f: F,
    state: Option<T>,
    fut: Option<Fut>,
}

impl<T, F, Fut: Unpin> Unpin for Unfold<T, F, Fut> {}

impl<T, F, Fut> fmt::Debug for Unfold<T, F, Fut>
where
    T: fmt::Debug,
    Fut: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Unfold")
            .field("state", &self.state)
            .field("fut", &self.fut)
            .finish()
    }
}

impl<T, F, Fut> Unfold<T, F, Fut> {
    unsafe_unpinned!(f: F);
    unsafe_unpinned!(state: Option<T>);
    unsafe_pinned!(fut: Option<Fut>);
}

impl<T, F, Fut, Item> FusedStream for Unfold<T, F, Fut>
    where F: FnMut(T) -> Fut,
          Fut: Future<Output = Option<(Item, T)>>,
{
    fn is_terminated(&self) -> bool {
        self.state.is_none() && self.fut.is_none()
    }
}

impl<T, F, Fut, Item> Stream for Unfold<T, F, Fut>
    where F: FnMut(T) -> Fut,
          Fut: Future<Output = Option<(Item, T)>>,
{
    type Item = Item;

    fn poll_next(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Self::Item>> {
        if let Some(state) = self.as_mut().state().take() {
            let fut = (self.as_mut().f())(state);
            self.as_mut().fut().set(Some(fut));
        }

        let step = ready!(self.as_mut().fut().as_pin_mut()
            .expect("Unfold must not be polled after it returned `Poll::Ready(None)`").poll(cx));
        self.as_mut().fut().set(None);

        if let Some((item, next_state)) = step {
            *self.as_mut().state() = Some(next_state);
            Poll::Ready(Some(item))
        } else {
            Poll::Ready(None)
        }
    }
}
<|endoftext|>


<commit_before>//! Completion tests for item specifics overall.
//!
//! Except for use items which are tested in [super::use_tree] and mod declarations with are tested
//! in [crate::completions::mod_].
use expect_test::{expect, Expect};

use crate::tests::{completion_list, BASE_ITEMS_FIXTURE};

fn check(ra_fixture: &str, expect: Expect) {
    let actual = completion_list(&format!("{}{}", BASE_ITEMS_FIXTURE, ra_fixture));
    expect.assert_eq(&actual)
}

#[test]
fn target_type_or_trait_in_impl_block() {
    check(
        r#"
impl Tra$0
"#,
        expect![[r##"
            kw self
            kw super
            kw crate
            tt Trait
            en Enum
            st Record
            st Tuple
            md module
            st Unit
            ma makro!(…) #[macro_export] macro_rules! makro
            un Union
            bt u32
        "##]],
    )
}

#[test]
fn target_type_in_trait_impl_block() {
    check(
        r#"
impl Trait for Str$0
"#,
        expect![[r##"
            kw self
            kw super
            kw crate
            tt Trait
            en Enum
            st Record
            st Tuple
            md module
            st Unit
            ma makro!(…) #[macro_export] macro_rules! makro
            un Union
            bt u32
        "##]],
    )
}

#[test]
fn after_trait_name_in_trait_def() {
    check(
        r"trait A $0",
        expect![[r#"
            kw where
        "#]],
    );
}

#[test]
fn after_target_name_in_impl() {
    check(
        r"impl Trait $0",
        expect![[r#"
            kw where
            kw for
        "#]],
    );
    // FIXME: This should emit `kw where`
    check(r"impl Trait for Type $0", expect![[r#""#]]);
}

#[test]
fn before_record_field() {
    check(
        r#"
struct Foo {
    $0
    pub f: i32,
}
"#,
        expect![[r#"
            kw pub(crate)
            kw pub
        "#]],
    )
}
<commit_msg>Add completion tests for cursor after items<commit_after>//! Completion tests for item specifics overall.
//!
//! Except for use items which are tested in [super::use_tree] and mod declarations with are tested
//! in [crate::completions::mod_].
use expect_test::{expect, Expect};

use crate::tests::{completion_list, BASE_ITEMS_FIXTURE};

fn check(ra_fixture: &str, expect: Expect) {
    let actual = completion_list(&format!("{}{}", BASE_ITEMS_FIXTURE, ra_fixture));
    expect.assert_eq(&actual)
}

#[test]
fn target_type_or_trait_in_impl_block() {
    check(
        r#"
impl Tra$0
"#,
        expect![[r##"
            kw self
            kw super
            kw crate
            tt Trait
            en Enum
            st Record
            st Tuple
            md module
            st Unit
            ma makro!(…) #[macro_export] macro_rules! makro
            un Union
            bt u32
        "##]],
    )
}

#[test]
fn target_type_in_trait_impl_block() {
    check(
        r#"
impl Trait for Str$0
"#,
        expect![[r##"
            kw self
            kw super
            kw crate
            tt Trait
            en Enum
            st Record
            st Tuple
            md module
            st Unit
            ma makro!(…) #[macro_export] macro_rules! makro
            un Union
            bt u32
        "##]],
    )
}

#[test]
fn after_trait_name_in_trait_def() {
    check(
        r"trait A $0",
        expect![[r#"
            kw where
        "#]],
    );
}

#[test]
fn after_target_name_in_impl() {
    check(
        r"impl Trait $0",
        expect![[r#"
            kw where
            kw for
        "#]],
    );
    // FIXME: This should emit `kw where`
    check(r"impl Trait for Type $0", expect![[r#""#]]);
}

#[test]
fn after_struct_name() {
    // FIXME: This should emit `kw where` only
    check(
        r"struct Struct $0",
        expect![[r##"
            kw pub(crate)
            kw pub
            kw unsafe
            kw fn
            kw const
            kw type
            kw impl
            kw extern
            kw use
            kw trait
            kw static
            kw mod
            kw enum
            kw struct
            kw union
            sn tmod (Test module)
            sn tfn (Test function)
            sn macro_rules
            kw self
            kw super
            kw crate
            md module
            ma makro!(…)           #[macro_export] macro_rules! makro
        "##]],
    );
}

#[test]
fn after_fn_name() {
    // FIXME: This should emit `kw where` only
    check(
        r"fn func() $0",
        expect![[r##"
            kw pub(crate)
            kw pub
            kw unsafe
            kw fn
            kw const
            kw type
            kw impl
            kw extern
            kw use
            kw trait
            kw static
            kw mod
            kw enum
            kw struct
            kw union
            sn tmod (Test module)
            sn tfn (Test function)
            sn macro_rules
            kw self
            kw super
            kw crate
            md module
            ma makro!(…)           #[macro_export] macro_rules! makro
        "##]],
    );
}

#[test]
fn before_record_field() {
    check(
        r#"
struct Foo {
    $0
    pub f: i32,
}
"#,
        expect![[r#"
            kw pub(crate)
            kw pub
        "#]],
    )
}
<|endoftext|>


<commit_before>#![feature(stdsimd)]

extern crate cupid;
#[macro_use]
extern crate std_detect;

#[test]
fn dump() {
    println!("aes: {:?}", is_x86_feature_detected!("aes"));
    println!("pclmulqdq: {:?}", is_x86_feature_detected!("pclmulqdq"));
    println!("rdrand: {:?}", is_x86_feature_detected!("rdrand"));
    println!("rdseed: {:?}", is_x86_feature_detected!("rdseed"));
    println!("tsc: {:?}", is_x86_feature_detected!("tsc"));
    println!("sse: {:?}", is_x86_feature_detected!("sse"));
    println!("sse2: {:?}", is_x86_feature_detected!("sse2"));
    println!("sse3: {:?}", is_x86_feature_detected!("sse3"));
    println!("ssse3: {:?}", is_x86_feature_detected!("ssse3"));
    println!("sse4.1: {:?}", is_x86_feature_detected!("sse4.1"));
    println!("sse4.2: {:?}", is_x86_feature_detected!("sse4.2"));
    println!("sse4a: {:?}", is_x86_feature_detected!("sse4a"));
    println!("sha: {:?}", is_x86_feature_detected!("sha"));
    println!("avx: {:?}", is_x86_feature_detected!("avx"));
    println!("avx2: {:?}", is_x86_feature_detected!("avx2"));
    println!("avx512f {:?}", is_x86_feature_detected!("avx512f"));
    println!("avx512cd {:?}", is_x86_feature_detected!("avx512cd"));
    println!("avx512er {:?}", is_x86_feature_detected!("avx512er"));
    println!("avx512pf {:?}", is_x86_feature_detected!("avx512pf"));
    println!("avx512bw {:?}", is_x86_feature_detected!("avx512bw"));
    println!("avx512dq {:?}", is_x86_feature_detected!("avx512dq"));
    println!("avx512vl {:?}", is_x86_feature_detected!("avx512vl"));
    println!("avx512_ifma {:?}", is_x86_feature_detected!("avx512ifma"));
    println!("avx512_vbmi {:?}", is_x86_feature_detected!("avx512vbmi"));
    println!(
        "avx512_vpopcntdq {:?}",
        is_x86_feature_detected!("avx512vpopcntdq")
    );
    println!("fma: {:?}", is_x86_feature_detected!("fma"));
    println!("abm: {:?}", is_x86_feature_detected!("abm"));
    println!("bmi: {:?}", is_x86_feature_detected!("bmi1"));
    println!("bmi2: {:?}", is_x86_feature_detected!("bmi2"));
    println!("tbm: {:?}", is_x86_feature_detected!("tbm"));
    println!("popcnt: {:?}", is_x86_feature_detected!("popcnt"));
    println!("lzcnt: {:?}", is_x86_feature_detected!("lzcnt"));
    println!("fxsr: {:?}", is_x86_feature_detected!("fxsr"));
    println!("xsave: {:?}", is_x86_feature_detected!("xsave"));
    println!("xsaveopt: {:?}", is_x86_feature_detected!("xsaveopt"));
    println!("xsaves: {:?}", is_x86_feature_detected!("xsaves"));
    println!("xsavec: {:?}", is_x86_feature_detected!("xsavec"));
    println!("cmpxchg16b: {:?}", is_x86_feature_detected!("cmpxchg16b"));
    println!("adx: {:?}", is_x86_feature_detected!("adx"));
    println!("rtm: {:?}", is_x86_feature_detected!("rtm"));
}

#[cfg(feature = "std_detect_env_override")]
#[test]
fn env_override_no_avx() {
    if let Ok(disable) = std::env::var("RUST_STD_DETECT_UNSTABLE") {
        let information = cupid::master().unwrap();
        for d in disable.split(" ") {
            match d {
                "avx" => {
                    if information.avx() {
                        assert_ne!(is_x86_feature_detected!("avx"), information.avx())
                    }
                }
                "avx2" => {
                    if information.avx2() {
                        assert_ne!(is_x86_feature_detected!("avx2"), information.avx2())
                    }
                }
                _ => {}
            }
        }
    }
}

#[test]
fn compare_with_cupid() {
    let information = cupid::master().unwrap();
    assert_eq!(is_x86_feature_detected!("aes"), information.aesni());
    assert_eq!(
        is_x86_feature_detected!("pclmulqdq"),
        information.pclmulqdq()
    );
    assert_eq!(is_x86_feature_detected!("rdrand"), information.rdrand());
    assert_eq!(is_x86_feature_detected!("rdseed"), information.rdseed());
    assert_eq!(is_x86_feature_detected!("tsc"), information.tsc());
    assert_eq!(is_x86_feature_detected!("sse"), information.sse());
    assert_eq!(is_x86_feature_detected!("sse2"), information.sse2());
    assert_eq!(is_x86_feature_detected!("sse3"), information.sse3());
    assert_eq!(is_x86_feature_detected!("ssse3"), information.ssse3());
    assert_eq!(is_x86_feature_detected!("sse4.1"), information.sse4_1());
    assert_eq!(is_x86_feature_detected!("sse4.2"), information.sse4_2());
    assert_eq!(is_x86_feature_detected!("sse4a"), information.sse4a());
    assert_eq!(is_x86_feature_detected!("sha"), information.sha());
    assert_eq!(is_x86_feature_detected!("avx"), information.avx());
    assert_eq!(is_x86_feature_detected!("avx2"), information.avx2());
    assert_eq!(is_x86_feature_detected!("avx512f"), information.avx512f());
    assert_eq!(is_x86_feature_detected!("avx512cd"), information.avx512cd());
    assert_eq!(is_x86_feature_detected!("avx512er"), information.avx512er());
    assert_eq!(is_x86_feature_detected!("avx512pf"), information.avx512pf());
    assert_eq!(is_x86_feature_detected!("avx512bw"), information.avx512bw());
    assert_eq!(is_x86_feature_detected!("avx512dq"), information.avx512dq());
    assert_eq!(is_x86_feature_detected!("avx512vl"), information.avx512vl());
    assert_eq!(
        is_x86_feature_detected!("avx512ifma"),
        information.avx512_ifma()
    );
    assert_eq!(
        is_x86_feature_detected!("avx512vbmi"),
        information.avx512_vbmi()
    );
    assert_eq!(
        is_x86_feature_detected!("avx512vpopcntdq"),
        information.avx512_vpopcntdq()
    );
    assert_eq!(is_x86_feature_detected!("fma"), information.fma());
    assert_eq!(is_x86_feature_detected!("bmi1"), information.bmi1());
    assert_eq!(is_x86_feature_detected!("bmi2"), information.bmi2());
    assert_eq!(is_x86_feature_detected!("popcnt"), information.popcnt());
    assert_eq!(is_x86_feature_detected!("abm"), information.lzcnt());
    assert_eq!(is_x86_feature_detected!("tbm"), information.tbm());
    assert_eq!(is_x86_feature_detected!("lzcnt"), information.lzcnt());
    assert_eq!(is_x86_feature_detected!("xsave"), information.xsave());
    assert_eq!(is_x86_feature_detected!("xsaveopt"), information.xsaveopt());
    assert_eq!(
        is_x86_feature_detected!("xsavec"),
        information.xsavec_and_xrstor()
    );
    assert_eq!(
        is_x86_feature_detected!("xsaves"),
        information.xsaves_xrstors_and_ia32_xss()
    );
    assert_eq!(
        is_x86_feature_detected!("cmpxchg16b"),
        information.cmpxchg16b(),
    );
    assert_eq!(is_x86_feature_detected!("adx"), information.adx(),);
    assert_eq!(is_x86_feature_detected!("rtm"), information.rtm(),);
}
<commit_msg>Unbreak non-x86<commit_after>#![feature(stdsimd)]
#![cfg(any(target_arch = "x86", target_arch = "x86_64"))]

extern crate cupid;
#[macro_use]
extern crate std_detect;

#[test]
fn dump() {
    println!("aes: {:?}", is_x86_feature_detected!("aes"));
    println!("pclmulqdq: {:?}", is_x86_feature_detected!("pclmulqdq"));
    println!("rdrand: {:?}", is_x86_feature_detected!("rdrand"));
    println!("rdseed: {:?}", is_x86_feature_detected!("rdseed"));
    println!("tsc: {:?}", is_x86_feature_detected!("tsc"));
    println!("sse: {:?}", is_x86_feature_detected!("sse"));
    println!("sse2: {:?}", is_x86_feature_detected!("sse2"));
    println!("sse3: {:?}", is_x86_feature_detected!("sse3"));
    println!("ssse3: {:?}", is_x86_feature_detected!("ssse3"));
    println!("sse4.1: {:?}", is_x86_feature_detected!("sse4.1"));
    println!("sse4.2: {:?}", is_x86_feature_detected!("sse4.2"));
    println!("sse4a: {:?}", is_x86_feature_detected!("sse4a"));
    println!("sha: {:?}", is_x86_feature_detected!("sha"));
    println!("avx: {:?}", is_x86_feature_detected!("avx"));
    println!("avx2: {:?}", is_x86_feature_detected!("avx2"));
    println!("avx512f {:?}", is_x86_feature_detected!("avx512f"));
    println!("avx512cd {:?}", is_x86_feature_detected!("avx512cd"));
    println!("avx512er {:?}", is_x86_feature_detected!("avx512er"));
    println!("avx512pf {:?}", is_x86_feature_detected!("avx512pf"));
    println!("avx512bw {:?}", is_x86_feature_detected!("avx512bw"));
    println!("avx512dq {:?}", is_x86_feature_detected!("avx512dq"));
    println!("avx512vl {:?}", is_x86_feature_detected!("avx512vl"));
    println!("avx512_ifma {:?}", is_x86_feature_detected!("avx512ifma"));
    println!("avx512_vbmi {:?}", is_x86_feature_detected!("avx512vbmi"));
    println!(
        "avx512_vpopcntdq {:?}",
        is_x86_feature_detected!("avx512vpopcntdq")
    );
    println!("fma: {:?}", is_x86_feature_detected!("fma"));
    println!("abm: {:?}", is_x86_feature_detected!("abm"));
    println!("bmi: {:?}", is_x86_feature_detected!("bmi1"));
    println!("bmi2: {:?}", is_x86_feature_detected!("bmi2"));
    println!("tbm: {:?}", is_x86_feature_detected!("tbm"));
    println!("popcnt: {:?}", is_x86_feature_detected!("popcnt"));
    println!("lzcnt: {:?}", is_x86_feature_detected!("lzcnt"));
    println!("fxsr: {:?}", is_x86_feature_detected!("fxsr"));
    println!("xsave: {:?}", is_x86_feature_detected!("xsave"));
    println!("xsaveopt: {:?}", is_x86_feature_detected!("xsaveopt"));
    println!("xsaves: {:?}", is_x86_feature_detected!("xsaves"));
    println!("xsavec: {:?}", is_x86_feature_detected!("xsavec"));
    println!("cmpxchg16b: {:?}", is_x86_feature_detected!("cmpxchg16b"));
    println!("adx: {:?}", is_x86_feature_detected!("adx"));
    println!("rtm: {:?}", is_x86_feature_detected!("rtm"));
}

#[cfg(feature = "std_detect_env_override")]
#[test]
fn env_override_no_avx() {
    if let Ok(disable) = std::env::var("RUST_STD_DETECT_UNSTABLE") {
        let information = cupid::master().unwrap();
        for d in disable.split(" ") {
            match d {
                "avx" => {
                    if information.avx() {
                        assert_ne!(is_x86_feature_detected!("avx"), information.avx())
                    }
                }
                "avx2" => {
                    if information.avx2() {
                        assert_ne!(is_x86_feature_detected!("avx2"), information.avx2())
                    }
                }
                _ => {}
            }
        }
    }
}

#[test]
fn compare_with_cupid() {
    let information = cupid::master().unwrap();
    assert_eq!(is_x86_feature_detected!("aes"), information.aesni());
    assert_eq!(
        is_x86_feature_detected!("pclmulqdq"),
        information.pclmulqdq()
    );
    assert_eq!(is_x86_feature_detected!("rdrand"), information.rdrand());
    assert_eq!(is_x86_feature_detected!("rdseed"), information.rdseed());
    assert_eq!(is_x86_feature_detected!("tsc"), information.tsc());
    assert_eq!(is_x86_feature_detected!("sse"), information.sse());
    assert_eq!(is_x86_feature_detected!("sse2"), information.sse2());
    assert_eq!(is_x86_feature_detected!("sse3"), information.sse3());
    assert_eq!(is_x86_feature_detected!("ssse3"), information.ssse3());
    assert_eq!(is_x86_feature_detected!("sse4.1"), information.sse4_1());
    assert_eq!(is_x86_feature_detected!("sse4.2"), information.sse4_2());
    assert_eq!(is_x86_feature_detected!("sse4a"), information.sse4a());
    assert_eq!(is_x86_feature_detected!("sha"), information.sha());
    assert_eq!(is_x86_feature_detected!("avx"), information.avx());
    assert_eq!(is_x86_feature_detected!("avx2"), information.avx2());
    assert_eq!(is_x86_feature_detected!("avx512f"), information.avx512f());
    assert_eq!(is_x86_feature_detected!("avx512cd"), information.avx512cd());
    assert_eq!(is_x86_feature_detected!("avx512er"), information.avx512er());
    assert_eq!(is_x86_feature_detected!("avx512pf"), information.avx512pf());
    assert_eq!(is_x86_feature_detected!("avx512bw"), information.avx512bw());
    assert_eq!(is_x86_feature_detected!("avx512dq"), information.avx512dq());
    assert_eq!(is_x86_feature_detected!("avx512vl"), information.avx512vl());
    assert_eq!(
        is_x86_feature_detected!("avx512ifma"),
        information.avx512_ifma()
    );
    assert_eq!(
        is_x86_feature_detected!("avx512vbmi"),
        information.avx512_vbmi()
    );
    assert_eq!(
        is_x86_feature_detected!("avx512vpopcntdq"),
        information.avx512_vpopcntdq()
    );
    assert_eq!(is_x86_feature_detected!("fma"), information.fma());
    assert_eq!(is_x86_feature_detected!("bmi1"), information.bmi1());
    assert_eq!(is_x86_feature_detected!("bmi2"), information.bmi2());
    assert_eq!(is_x86_feature_detected!("popcnt"), information.popcnt());
    assert_eq!(is_x86_feature_detected!("abm"), information.lzcnt());
    assert_eq!(is_x86_feature_detected!("tbm"), information.tbm());
    assert_eq!(is_x86_feature_detected!("lzcnt"), information.lzcnt());
    assert_eq!(is_x86_feature_detected!("xsave"), information.xsave());
    assert_eq!(is_x86_feature_detected!("xsaveopt"), information.xsaveopt());
    assert_eq!(
        is_x86_feature_detected!("xsavec"),
        information.xsavec_and_xrstor()
    );
    assert_eq!(
        is_x86_feature_detected!("xsaves"),
        information.xsaves_xrstors_and_ia32_xss()
    );
    assert_eq!(
        is_x86_feature_detected!("cmpxchg16b"),
        information.cmpxchg16b(),
    );
    assert_eq!(is_x86_feature_detected!("adx"), information.adx(),);
    assert_eq!(is_x86_feature_detected!("rtm"), information.rtm(),);
}
<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use prometheus::{CounterVec, HistogramVec, Histogram};

lazy_static! {
    pub static ref PD_REQ_COUNTER_VEC: CounterVec =
        register_counter_vec!(
            "tikv_raftstore_pd_request_sent_total",
            "Total number of pd client request sent.",
            &["type", "status"]
        ).unwrap();

    pub static ref PD_HEARTBEAT_COUNTER_VEC: CounterVec =
        register_counter_vec!(
            "tikv_raftstore_pd_heartbeat_sent_total",
            "Total number of raftstore pd client heartbeat sent.",
            &["type"]
        ).unwrap();

    pub static ref PD_VALIDATE_PEER_COUNTER_VEC: CounterVec =
        register_counter_vec!(
            "tikv_raftstore_pd_validate_peer_total",
            "Total number of raftstore pd worker validate peer task.",
            &["type"]
        ).unwrap();

    pub static ref SNAP_COUNTER_VEC: CounterVec =
        register_counter_vec!(
            "tikv_raftstore_snapshot_total",
            "Total number of raftstore snapshot processed.",
            &["type", "status"]
        ).unwrap();

    pub static ref CHECK_SPILT_COUNTER_VEC: CounterVec =
        register_counter_vec!(
            "tikv_raftstore_check_split_total",
            "Total number of raftstore split check.",
            &["type"]
        ).unwrap();

    pub static ref SNAP_HISTOGRAM: HistogramVec =
        register_histogram_vec!(
            "tikv_raftstore_snapshot_duration_seconds",
            "Bucketed histogram of raftstore snapshot process duration",
            &["type"]
        ).unwrap();

    pub static ref CHECK_SPILT_HISTOGRAM: Histogram =
        register_histogram!(
            "tikv_raftstore_check_split_duration_seconds",
            "Bucketed histogram of raftstore split check duration"
        ).unwrap();

    pub static ref COMPACT_RANGE_CF: HistogramVec =
        register_histogram_vec!(
            "tikv_compact_range_cf_duration_seconds",
            "Bucketed histogram of compact range for cf execution",
            &["cf"]
        ).unwrap();

    pub static ref REGION_HASH_HISTOGRAM: Histogram =
        register_histogram!(
            "tikv_raftstore_hash_duration_seconds",
            "Bucketed histogram of raftstore hash compution duration"
        ).unwrap();

    pub static ref APPLY_PROPOSAL: Histogram =
        register_histogram!(
            "tikv_raftstore_apply_proposal",
            "Proposal count of every region in a mio tick"
        ).unwrap();
}
<commit_msg>metrics: adjust buckets (#1999)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use prometheus::{CounterVec, HistogramVec, Histogram, exponential_buckets};

lazy_static! {
    pub static ref PD_REQ_COUNTER_VEC: CounterVec =
        register_counter_vec!(
            "tikv_raftstore_pd_request_sent_total",
            "Total number of pd client request sent.",
            &["type", "status"]
        ).unwrap();

    pub static ref PD_HEARTBEAT_COUNTER_VEC: CounterVec =
        register_counter_vec!(
            "tikv_raftstore_pd_heartbeat_sent_total",
            "Total number of raftstore pd client heartbeat sent.",
            &["type"]
        ).unwrap();

    pub static ref PD_VALIDATE_PEER_COUNTER_VEC: CounterVec =
        register_counter_vec!(
            "tikv_raftstore_pd_validate_peer_total",
            "Total number of raftstore pd worker validate peer task.",
            &["type"]
        ).unwrap();

    pub static ref SNAP_COUNTER_VEC: CounterVec =
        register_counter_vec!(
            "tikv_raftstore_snapshot_total",
            "Total number of raftstore snapshot processed.",
            &["type", "status"]
        ).unwrap();

    pub static ref CHECK_SPILT_COUNTER_VEC: CounterVec =
        register_counter_vec!(
            "tikv_raftstore_check_split_total",
            "Total number of raftstore split check.",
            &["type"]
        ).unwrap();

    pub static ref SNAP_HISTOGRAM: HistogramVec =
        register_histogram_vec!(
            "tikv_raftstore_snapshot_duration_seconds",
            "Bucketed histogram of raftstore snapshot process duration",
            &["type"],
            exponential_buckets(0.0005, 2.0, 20).unwrap()
        ).unwrap();

    pub static ref CHECK_SPILT_HISTOGRAM: Histogram =
        register_histogram!(
            "tikv_raftstore_check_split_duration_seconds",
            "Bucketed histogram of raftstore split check duration",
            exponential_buckets(0.0005, 2.0, 20).unwrap()
        ).unwrap();

    pub static ref COMPACT_RANGE_CF: HistogramVec =
        register_histogram_vec!(
            "tikv_compact_range_cf_duration_seconds",
            "Bucketed histogram of compact range for cf execution",
            &["cf"]
        ).unwrap();

    pub static ref REGION_HASH_HISTOGRAM: Histogram =
        register_histogram!(
            "tikv_raftstore_hash_duration_seconds",
            "Bucketed histogram of raftstore hash compution duration"
        ).unwrap();

    pub static ref APPLY_PROPOSAL: Histogram =
        register_histogram!(
            "tikv_raftstore_apply_proposal",
            "Proposal count of every region in a mio tick"
        ).unwrap();
}
<|endoftext|>