<commit_before>use crate::utils::paths;
use crate::utils::{
    get_trait_def_id, is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note,
    span_lint_and_then,
};
use if_chain::if_chain;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, NestedVisitorMap, Visitor};
use rustc_hir::{
    BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, HirId, Item, ItemKind, TraitRef, UnsafeSource, Unsafety,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for deriving `Hash` but implementing `PartialEq`
    /// explicitly or vice versa.
    ///
    /// **Why is this bad?** The implementation of these traits must agree (for
    /// example for use with `HashMap`) so it’s probably a bad idea to use a
    /// default-generated `Hash` implementation with an explicitly defined
    /// `PartialEq`. In particular, the following must hold for any type:
    ///
    /// ```text
    /// k1 == k2 ⇒ hash(k1) == hash(k2)
    /// ```
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```ignore
    /// #[derive(Hash)]
    /// struct Foo;
    ///
    /// impl PartialEq for Foo {
    ///     ...
    /// }
    /// ```
    pub DERIVE_HASH_XOR_EQ,
    correctness,
    "deriving `Hash` but implementing `PartialEq` explicitly"
}

declare_clippy_lint! {
    /// **What it does:** Checks for deriving `Ord` but implementing `PartialOrd`
    /// explicitly or vice versa.
    ///
    /// **Why is this bad?** The implementation of these traits must agree (for
    /// example for use with `sort`) so it’s probably a bad idea to use a
    /// default-generated `Ord` implementation with an explicitly defined
    /// `PartialOrd`. In particular, the following must hold for any type
    /// implementing `Ord`:
    ///
    /// ```text
    /// k1.cmp(&k2) == k1.partial_cmp(&k2).unwrap()
    /// ```
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust,ignore
    /// #[derive(Ord, PartialEq, Eq)]
    /// struct Foo;
    ///
    /// impl PartialOrd for Foo {
    ///     ...
    /// }
    /// ```
    /// Use instead:
    /// ```rust,ignore
    /// #[derive(PartialEq, Eq)]
    /// struct Foo;
    ///
    /// impl PartialOrd for Foo {
    ///     fn partial_cmp(&self, other: &Foo) -> Option<Ordering> {
    ///        Some(self.cmp(other))
    ///     }
    /// }
    ///
    /// impl Ord for Foo {
    ///     ...
    /// }
    /// ```
    /// or, if you don't need a custom ordering:
    /// ```rust,ignore
    /// #[derive(Ord, PartialOrd, PartialEq, Eq)]
    /// struct Foo;
    /// ```
    pub DERIVE_ORD_XOR_PARTIAL_ORD,
    correctness,
    "default lint description"
}

declare_clippy_lint! {
    /// **What it does:** Checks for explicit `Clone` implementations for `Copy`
    /// types.
    ///
    /// **Why is this bad?** To avoid surprising behaviour, these traits should
    /// agree and the behaviour of `Copy` cannot be overridden. In almost all
    /// situations a `Copy` type should have a `Clone` implementation that does
    /// nothing more than copy the object, which is what `#[derive(Copy, Clone)]`
    /// gets you.
    ///
    /// **Known problems:** Bounds of generic types are sometimes wrong: https://github.com/rust-lang/rust/issues/26925
    ///
    /// **Example:**
    /// ```rust,ignore
    /// #[derive(Copy)]
    /// struct Foo;
    ///
    /// impl Clone for Foo {
    ///     // ..
    /// }
    /// ```
    pub EXPL_IMPL_CLONE_ON_COPY,
    pedantic,
    "implementing `Clone` explicitly on `Copy` types"
}

declare_clippy_lint! {
    /// **What it does:** Checks for deriving `serde::Deserialize` on a type that
    /// has methods using `unsafe`.
    ///
    /// **Why is this bad?** Deriving `serde::Deserialize` will create a constructor
    /// that may violate invariants hold by another constructor.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust,ignore
    /// use serde::Deserialize;
    ///
    /// #[derive(Deserialize)]
    /// pub struct Foo {
    ///     // ..
    /// }
    ///
    /// impl Foo {
    ///     pub fn new() -> Self {
    ///         // setup here ..
    ///     }
    ///
    ///     pub unsafe fn parts() -> (&str, &str) {
    ///         // assumes invariants hold
    ///     }
    /// }
    /// ```
    pub UNSAFE_DERIVE_DESERIALIZE,
    pedantic,
    "deriving `serde::Deserialize` on a type that has methods using `unsafe`"
}

declare_lint_pass!(Derive => [
    EXPL_IMPL_CLONE_ON_COPY,
    DERIVE_HASH_XOR_EQ,
    DERIVE_ORD_XOR_PARTIAL_ORD,
    UNSAFE_DERIVE_DESERIALIZE
]);

impl<'tcx> LateLintPass<'tcx> for Derive {
    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
        if let ItemKind::Impl {
            of_trait: Some(ref trait_ref),
            ..
        } = item.kind
        {
            let ty = cx.tcx.type_of(cx.tcx.hir().local_def_id(item.hir_id));
            let is_automatically_derived = is_automatically_derived(&*item.attrs);

            check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);
            check_ord_partial_ord(cx, item.span, trait_ref, ty, is_automatically_derived);

            if is_automatically_derived {
                check_unsafe_derive_deserialize(cx, item, trait_ref, ty);
            } else {
                check_copy_clone(cx, item, trait_ref, ty);
            }
        }
    }
}

/// Implementation of the `DERIVE_HASH_XOR_EQ` lint.
fn check_hash_peq<'tcx>(
    cx: &LateContext<'tcx>,
    span: Span,
    trait_ref: &TraitRef<'_>,
    ty: Ty<'tcx>,
    hash_is_automatically_derived: bool,
) {
    if_chain! {
        if match_path(&trait_ref.path, &paths::HASH);
        if let Some(peq_trait_def_id) = cx.tcx.lang_items().eq_trait();
        if let Some(def_id) = &trait_ref.trait_def_id();
        if !def_id.is_local();
        then {
            // Look for the PartialEq implementations for `ty`
            cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| {
                let peq_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id));

                if peq_is_automatically_derived == hash_is_automatically_derived {
                    return;
                }

                let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation");

                // Only care about `impl PartialEq<Foo> for Foo`
                // For `impl PartialEq<B> for A, input_types is [A, B]
                if trait_ref.substs.type_at(1) == ty {
                    let mess = if peq_is_automatically_derived {
                        "you are implementing `Hash` explicitly but have derived `PartialEq`"
                    } else {
                        "you are deriving `Hash` but have implemented `PartialEq` explicitly"
                    };

                    span_lint_and_then(
                        cx,
                        DERIVE_HASH_XOR_EQ,
                        span,
                        mess,
                        |diag| {
                            if let Some(local_def_id) = impl_id.as_local() {
                                let hir_id = cx.tcx.hir().as_local_hir_id(local_def_id);
                                diag.span_note(
                                    cx.tcx.hir().span(hir_id),
                                    "`PartialEq` implemented here"
                                );
                            }
                        }
                    );
                }
            });
        }
    }
}

/// Implementation of the `DERIVE_ORD_XOR_PARTIAL_ORD` lint.
fn check_ord_partial_ord<'tcx>(
    cx: &LateContext<'tcx>,
    span: Span,
    trait_ref: &TraitRef<'_>,
    ty: Ty<'tcx>,
    ord_is_automatically_derived: bool,
) {
    if_chain! {
        if let Some(ord_trait_def_id) = get_trait_def_id(cx, &paths::ORD);
        if let Some(partial_ord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait();
        if let Some(def_id) = &trait_ref.trait_def_id();
        if *def_id == ord_trait_def_id;
        then {
            // Look for the PartialOrd implementations for `ty`
            cx.tcx.for_each_relevant_impl(partial_ord_trait_def_id, ty, |impl_id| {
                let partial_ord_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id));

                if partial_ord_is_automatically_derived == ord_is_automatically_derived {
                    return;
                }

                let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation");

                // Only care about `impl PartialOrd<Foo> for Foo`
                // For `impl PartialOrd<B> for A, input_types is [A, B]
                if trait_ref.substs.type_at(1) == ty {
                    let mess = if partial_ord_is_automatically_derived {
                        "you are implementing `Ord` explicitly but have derived `PartialOrd`"
                    } else {
                        "you are deriving `Ord` but have implemented `PartialOrd` explicitly"
                    };

                    span_lint_and_then(
                        cx,
                        DERIVE_ORD_XOR_PARTIAL_ORD,
                        span,
                        mess,
                        |diag| {
                            if let Some(local_def_id) = impl_id.as_local() {
                                let hir_id = cx.tcx.hir().as_local_hir_id(local_def_id);
                                diag.span_note(
                                    cx.tcx.hir().span(hir_id),
                                    "`PartialOrd` implemented here"
                                );
                            }
                        }
                    );
                }
            });
        }
    }
}

/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &TraitRef<'_>, ty: Ty<'tcx>) {
    if match_path(&trait_ref.path, &paths::CLONE_TRAIT) {
        if !is_copy(cx, ty) {
            return;
        }

        match ty.kind {
            ty::Adt(def, _) if def.is_union() => return,

            // Some types are not Clone by default but could be cloned “by hand” if necessary
            ty::Adt(def, substs) => {
                for variant in &def.variants {
                    for field in &variant.fields {
                        if let ty::FnDef(..) = field.ty(cx.tcx, substs).kind {
                            return;
                        }
                    }
                    for subst in substs {
                        if let ty::subst::GenericArgKind::Type(subst) = subst.unpack() {
                            if let ty::Param(_) = subst.kind {
                                return;
                            }
                        }
                    }
                }
            },
            _ => (),
        }

        span_lint_and_note(
            cx,
            EXPL_IMPL_CLONE_ON_COPY,
            item.span,
            "you are implementing `Clone` explicitly on a `Copy` type",
            Some(item.span),
            "consider deriving `Clone` or removing `Copy`",
        );
    }
}

/// Implementation of the `UNSAFE_DERIVE_DESERIALIZE` lint.
fn check_unsafe_derive_deserialize<'tcx>(
    cx: &LateContext<'tcx>,
    item: &Item<'_>,
    trait_ref: &TraitRef<'_>,
    ty: Ty<'tcx>,
) {
    fn item_from_def_id<'tcx>(cx: &LateContext<'tcx>, def_id: DefId) -> &'tcx Item<'tcx> {
        let hir_id = cx.tcx.hir().as_local_hir_id(def_id.expect_local());
        cx.tcx.hir().expect_item(hir_id)
    }

    fn has_unsafe<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>) -> bool {
        let mut visitor = UnsafeVisitor { cx, has_unsafe: false };
        walk_item(&mut visitor, item);
        visitor.has_unsafe
    }

    if_chain! {
        if match_path(&trait_ref.path, &paths::SERDE_DESERIALIZE);
        if let ty::Adt(def, _) = ty.kind;
        if def.did.is_local();
        if cx.tcx.inherent_impls(def.did)
            .iter()
            .map(|imp_did| item_from_def_id(cx, *imp_did))
            .any(|imp| has_unsafe(cx, imp));
        then {
            span_lint_and_help(
                cx,
                UNSAFE_DERIVE_DESERIALIZE,
                item.span,
                "you are deriving `serde::Deserialize` on a type that has methods using `unsafe`",
                None,
                "consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html"
            );
        }
    }
}

struct UnsafeVisitor<'a, 'tcx> {
    cx: &'a LateContext<'tcx>,
    has_unsafe: bool,
}

impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
    type Map = Map<'tcx>;

    fn visit_fn(&mut self, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body_id: BodyId, span: Span, id: HirId) {
        if self.has_unsafe {
            return;
        }

        if_chain! {
            if let Some(header) = kind.header();
            if let Unsafety::Unsafe = header.unsafety;
            then {
                self.has_unsafe = true;
            }
        }

        walk_fn(self, kind, decl, body_id, span, id);
    }

    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
        if self.has_unsafe {
            return;
        }

        if let ExprKind::Block(block, _) = expr.kind {
            match block.rules {
                BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided)
                | BlockCheckMode::PushUnsafeBlock(UnsafeSource::UserProvided)
                | BlockCheckMode::PopUnsafeBlock(UnsafeSource::UserProvided) => {
                    self.has_unsafe = true;
                },
                _ => {},
            }
        }

        walk_expr(self, expr);
    }

    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::All(self.cx.tcx.hir())
    }
}
<commit_msg>fill in lint description for DERIVE_ORD_XOR_PARTIAL_ORD<commit_after>use crate::utils::paths;
use crate::utils::{
    get_trait_def_id, is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, span_lint_and_then,
};
use if_chain::if_chain;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, NestedVisitorMap, Visitor};
use rustc_hir::{
    BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, HirId, Item, ItemKind, TraitRef, UnsafeSource, Unsafety,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for deriving `Hash` but implementing `PartialEq`
    /// explicitly or vice versa.
    ///
    /// **Why is this bad?** The implementation of these traits must agree (for
    /// example for use with `HashMap`) so it’s probably a bad idea to use a
    /// default-generated `Hash` implementation with an explicitly defined
    /// `PartialEq`. In particular, the following must hold for any type:
    ///
    /// ```text
    /// k1 == k2 ⇒ hash(k1) == hash(k2)
    /// ```
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```ignore
    /// #[derive(Hash)]
    /// struct Foo;
    ///
    /// impl PartialEq for Foo {
    ///     ...
    /// }
    /// ```
    pub DERIVE_HASH_XOR_EQ,
    correctness,
    "deriving `Hash` but implementing `PartialEq` explicitly"
}

declare_clippy_lint! {
    /// **What it does:** Checks for deriving `Ord` but implementing `PartialOrd`
    /// explicitly or vice versa.
    ///
    /// **Why is this bad?** The implementation of these traits must agree (for
    /// example for use with `sort`) so it’s probably a bad idea to use a
    /// default-generated `Ord` implementation with an explicitly defined
    /// `PartialOrd`. In particular, the following must hold for any type
    /// implementing `Ord`:
    ///
    /// ```text
    /// k1.cmp(&k2) == k1.partial_cmp(&k2).unwrap()
    /// ```
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust,ignore
    /// #[derive(Ord, PartialEq, Eq)]
    /// struct Foo;
    ///
    /// impl PartialOrd for Foo {
    ///     ...
    /// }
    /// ```
    /// Use instead:
    /// ```rust,ignore
    /// #[derive(PartialEq, Eq)]
    /// struct Foo;
    ///
    /// impl PartialOrd for Foo {
    ///     fn partial_cmp(&self, other: &Foo) -> Option<Ordering> {
    ///        Some(self.cmp(other))
    ///     }
    /// }
    ///
    /// impl Ord for Foo {
    ///     ...
    /// }
    /// ```
    /// or, if you don't need a custom ordering:
    /// ```rust,ignore
    /// #[derive(Ord, PartialOrd, PartialEq, Eq)]
    /// struct Foo;
    /// ```
    pub DERIVE_ORD_XOR_PARTIAL_ORD,
    correctness,
    "deriving `Ord` but implementing `PartialOrd` explicitly"
}

declare_clippy_lint! {
    /// **What it does:** Checks for explicit `Clone` implementations for `Copy`
    /// types.
    ///
    /// **Why is this bad?** To avoid surprising behaviour, these traits should
    /// agree and the behaviour of `Copy` cannot be overridden. In almost all
    /// situations a `Copy` type should have a `Clone` implementation that does
    /// nothing more than copy the object, which is what `#[derive(Copy, Clone)]`
    /// gets you.
    ///
    /// **Known problems:** Bounds of generic types are sometimes wrong: https://github.com/rust-lang/rust/issues/26925
    ///
    /// **Example:**
    /// ```rust,ignore
    /// #[derive(Copy)]
    /// struct Foo;
    ///
    /// impl Clone for Foo {
    ///     // ..
    /// }
    /// ```
    pub EXPL_IMPL_CLONE_ON_COPY,
    pedantic,
    "implementing `Clone` explicitly on `Copy` types"
}

declare_clippy_lint! {
    /// **What it does:** Checks for deriving `serde::Deserialize` on a type that
    /// has methods using `unsafe`.
    ///
    /// **Why is this bad?** Deriving `serde::Deserialize` will create a constructor
    /// that may violate invariants hold by another constructor.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust,ignore
    /// use serde::Deserialize;
    ///
    /// #[derive(Deserialize)]
    /// pub struct Foo {
    ///     // ..
    /// }
    ///
    /// impl Foo {
    ///     pub fn new() -> Self {
    ///         // setup here ..
    ///     }
    ///
    ///     pub unsafe fn parts() -> (&str, &str) {
    ///         // assumes invariants hold
    ///     }
    /// }
    /// ```
    pub UNSAFE_DERIVE_DESERIALIZE,
    pedantic,
    "deriving `serde::Deserialize` on a type that has methods using `unsafe`"
}

declare_lint_pass!(Derive => [
    EXPL_IMPL_CLONE_ON_COPY,
    DERIVE_HASH_XOR_EQ,
    DERIVE_ORD_XOR_PARTIAL_ORD,
    UNSAFE_DERIVE_DESERIALIZE
]);

impl<'tcx> LateLintPass<'tcx> for Derive {
    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
        if let ItemKind::Impl {
            of_trait: Some(ref trait_ref),
            ..
        } = item.kind
        {
            let ty = cx.tcx.type_of(cx.tcx.hir().local_def_id(item.hir_id));
            let is_automatically_derived = is_automatically_derived(&*item.attrs);

            check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);
            check_ord_partial_ord(cx, item.span, trait_ref, ty, is_automatically_derived);

            if is_automatically_derived {
                check_unsafe_derive_deserialize(cx, item, trait_ref, ty);
            } else {
                check_copy_clone(cx, item, trait_ref, ty);
            }
        }
    }
}

/// Implementation of the `DERIVE_HASH_XOR_EQ` lint.
fn check_hash_peq<'tcx>(
    cx: &LateContext<'tcx>,
    span: Span,
    trait_ref: &TraitRef<'_>,
    ty: Ty<'tcx>,
    hash_is_automatically_derived: bool,
) {
    if_chain! {
        if match_path(&trait_ref.path, &paths::HASH);
        if let Some(peq_trait_def_id) = cx.tcx.lang_items().eq_trait();
        if let Some(def_id) = &trait_ref.trait_def_id();
        if !def_id.is_local();
        then {
            // Look for the PartialEq implementations for `ty`
            cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| {
                let peq_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id));

                if peq_is_automatically_derived == hash_is_automatically_derived {
                    return;
                }

                let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation");

                // Only care about `impl PartialEq<Foo> for Foo`
                // For `impl PartialEq<B> for A, input_types is [A, B]
                if trait_ref.substs.type_at(1) == ty {
                    let mess = if peq_is_automatically_derived {
                        "you are implementing `Hash` explicitly but have derived `PartialEq`"
                    } else {
                        "you are deriving `Hash` but have implemented `PartialEq` explicitly"
                    };

                    span_lint_and_then(
                        cx,
                        DERIVE_HASH_XOR_EQ,
                        span,
                        mess,
                        |diag| {
                            if let Some(local_def_id) = impl_id.as_local() {
                                let hir_id = cx.tcx.hir().as_local_hir_id(local_def_id);
                                diag.span_note(
                                    cx.tcx.hir().span(hir_id),
                                    "`PartialEq` implemented here"
                                );
                            }
                        }
                    );
                }
            });
        }
    }
}

/// Implementation of the `DERIVE_ORD_XOR_PARTIAL_ORD` lint.
fn check_ord_partial_ord<'tcx>(
    cx: &LateContext<'tcx>,
    span: Span,
    trait_ref: &TraitRef<'_>,
    ty: Ty<'tcx>,
    ord_is_automatically_derived: bool,
) {
    if_chain! {
        if let Some(ord_trait_def_id) = get_trait_def_id(cx, &paths::ORD);
        if let Some(partial_ord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait();
        if let Some(def_id) = &trait_ref.trait_def_id();
        if *def_id == ord_trait_def_id;
        then {
            // Look for the PartialOrd implementations for `ty`
            cx.tcx.for_each_relevant_impl(partial_ord_trait_def_id, ty, |impl_id| {
                let partial_ord_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id));

                if partial_ord_is_automatically_derived == ord_is_automatically_derived {
                    return;
                }

                let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation");

                // Only care about `impl PartialOrd<Foo> for Foo`
                // For `impl PartialOrd<B> for A, input_types is [A, B]
                if trait_ref.substs.type_at(1) == ty {
                    let mess = if partial_ord_is_automatically_derived {
                        "you are implementing `Ord` explicitly but have derived `PartialOrd`"
                    } else {
                        "you are deriving `Ord` but have implemented `PartialOrd` explicitly"
                    };

                    span_lint_and_then(
                        cx,
                        DERIVE_ORD_XOR_PARTIAL_ORD,
                        span,
                        mess,
                        |diag| {
                            if let Some(local_def_id) = impl_id.as_local() {
                                let hir_id = cx.tcx.hir().as_local_hir_id(local_def_id);
                                diag.span_note(
                                    cx.tcx.hir().span(hir_id),
                                    "`PartialOrd` implemented here"
                                );
                            }
                        }
                    );
                }
            });
        }
    }
}

/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &TraitRef<'_>, ty: Ty<'tcx>) {
    if match_path(&trait_ref.path, &paths::CLONE_TRAIT) {
        if !is_copy(cx, ty) {
            return;
        }

        match ty.kind {
            ty::Adt(def, _) if def.is_union() => return,

            // Some types are not Clone by default but could be cloned “by hand” if necessary
            ty::Adt(def, substs) => {
                for variant in &def.variants {
                    for field in &variant.fields {
                        if let ty::FnDef(..) = field.ty(cx.tcx, substs).kind {
                            return;
                        }
                    }
                    for subst in substs {
                        if let ty::subst::GenericArgKind::Type(subst) = subst.unpack() {
                            if let ty::Param(_) = subst.kind {
                                return;
                            }
                        }
                    }
                }
            },
            _ => (),
        }

        span_lint_and_note(
            cx,
            EXPL_IMPL_CLONE_ON_COPY,
            item.span,
            "you are implementing `Clone` explicitly on a `Copy` type",
            Some(item.span),
            "consider deriving `Clone` or removing `Copy`",
        );
    }
}

/// Implementation of the `UNSAFE_DERIVE_DESERIALIZE` lint.
fn check_unsafe_derive_deserialize<'tcx>(
    cx: &LateContext<'tcx>,
    item: &Item<'_>,
    trait_ref: &TraitRef<'_>,
    ty: Ty<'tcx>,
) {
    fn item_from_def_id<'tcx>(cx: &LateContext<'tcx>, def_id: DefId) -> &'tcx Item<'tcx> {
        let hir_id = cx.tcx.hir().as_local_hir_id(def_id.expect_local());
        cx.tcx.hir().expect_item(hir_id)
    }

    fn has_unsafe<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>) -> bool {
        let mut visitor = UnsafeVisitor { cx, has_unsafe: false };
        walk_item(&mut visitor, item);
        visitor.has_unsafe
    }

    if_chain! {
        if match_path(&trait_ref.path, &paths::SERDE_DESERIALIZE);
        if let ty::Adt(def, _) = ty.kind;
        if def.did.is_local();
        if cx.tcx.inherent_impls(def.did)
            .iter()
            .map(|imp_did| item_from_def_id(cx, *imp_did))
            .any(|imp| has_unsafe(cx, imp));
        then {
            span_lint_and_help(
                cx,
                UNSAFE_DERIVE_DESERIALIZE,
                item.span,
                "you are deriving `serde::Deserialize` on a type that has methods using `unsafe`",
                None,
                "consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html"
            );
        }
    }
}

struct UnsafeVisitor<'a, 'tcx> {
    cx: &'a LateContext<'tcx>,
    has_unsafe: bool,
}

impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
    type Map = Map<'tcx>;

    fn visit_fn(&mut self, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body_id: BodyId, span: Span, id: HirId) {
        if self.has_unsafe {
            return;
        }

        if_chain! {
            if let Some(header) = kind.header();
            if let Unsafety::Unsafe = header.unsafety;
            then {
                self.has_unsafe = true;
            }
        }

        walk_fn(self, kind, decl, body_id, span, id);
    }

    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
        if self.has_unsafe {
            return;
        }

        if let ExprKind::Block(block, _) = expr.kind {
            match block.rules {
                BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided)
                | BlockCheckMode::PushUnsafeBlock(UnsafeSource::UserProvided)
                | BlockCheckMode::PopUnsafeBlock(UnsafeSource::UserProvided) => {
                    self.has_unsafe = true;
                },
                _ => {},
            }
        }

        walk_expr(self, expr);
    }

    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::All(self.cx.tcx.hir())
    }
}
<|endoftext|>


<commit_before>use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use if_chain::if_chain;
use crate::rustc::ty;
use crate::syntax::ast::LitKind;
use crate::syntax_pos::Span;
use crate::utils::paths;
use crate::utils::{in_macro, is_expn_of, last_path_segment, match_def_path, match_type, opt_def_id, resolve_node, snippet, span_lint_and_then, walk_ptrs_ty};
use crate::rustc_errors::Applicability;

/// **What it does:** Checks for the use of `format!("string literal with no
/// argument")` and `format!("{}", foo)` where `foo` is a string.
///
/// **Why is this bad?** There is no point of doing that. `format!("too")` can
/// be replaced by `"foo".to_owned()` if you really need a `String`. The even
/// worse `&format!("foo")` is often encountered in the wild. `format!("{}",
/// foo)` can be replaced by `foo.clone()` if `foo: String` or `foo.to_owned()`
/// if `foo: &str`.
///
/// **Known problems:** None.
///
/// **Examples:**
/// ```rust
/// format!("foo")
/// format!("{}", foo)
/// ```
declare_clippy_lint! {
    pub USELESS_FORMAT,
    complexity,
    "useless use of `format!`"
}

#[derive(Copy, Clone, Debug)]
pub struct Pass;

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array![USELESS_FORMAT]
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if let Some(span) = is_expn_of(expr.span, "format") {
            if in_macro(span) {
                return;
            }
            match expr.node {
                // `format!("{}", foo)` expansion
                ExprKind::Call(ref fun, ref args) => {
                    if_chain! {
                        if let ExprKind::Path(ref qpath) = fun.node;
                        if args.len() == 3;
                        if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id));
                        if match_def_path(cx.tcx, fun_def_id, &paths::FMT_ARGUMENTS_NEWV1FORMATTED);
                        if check_single_piece(&args[0]);
                        if let Some(format_arg) = get_single_string_arg(cx, &args[1]);
                        if check_unformatted(&args[2]);
                        if let ExprKind::AddrOf(_, ref format_arg) = format_arg.node;
                        then {
                            let (message, sugg) = if_chain! {
                                if let ExprKind::MethodCall(ref path, ref span, ref expr) = format_arg.node;
                                if path.ident.as_interned_str() == "to_string";
                                then {
                                    ("`to_string()` is enough",
                                    snippet(cx, format_arg.span, "<arg>").to_string())
                                } else {
                                    ("consider using .to_string()",
                                    format!("{}.to_string()", snippet(cx, format_arg.span, "<arg>")))
                                }
                            };

                            span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| {
                                db.span_suggestion_with_applicability(
                                    expr.span,
                                    message,
                                    sugg,
                                    Applicability::MachineApplicable,
                                );
                            });
                        }
                    }
                },
                // `format!("foo")` expansion contains `match () { () => [], }`
                ExprKind::Match(ref matchee, _, _) => if let ExprKind::Tup(ref tup) = matchee.node {
                    if tup.is_empty() {
                        let sugg = format!("{}.to_string()", snippet(cx, expr.span, "<expr>").into_owned());
                        span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| {
                            db.span_suggestion_with_applicability(
                                span,
                                "consider using .to_string()",
                                sugg,
                                Applicability::MachineApplicable, // snippet
                            );
                        });
                    }
                },
                _ => (),
            }
        }
    }
}

/// Checks if the expressions matches `&[""]`
fn check_single_piece(expr: &Expr) -> bool {
    if_chain! {
        if let ExprKind::AddrOf(_, ref expr) = expr.node; // &[""]
        if let ExprKind::Array(ref exprs) = expr.node; // [""]
        if exprs.len() == 1;
        if let ExprKind::Lit(ref lit) = exprs[0].node;
        if let LitKind::Str(ref lit, _) = lit.node;
        then {
            return lit.as_str().is_empty();
        }
    }

    false
}

/// Checks if the expressions matches
/// ```rust,ignore
/// &match (&"arg",) {
/// (__arg0,) => [::std::fmt::ArgumentV1::new(__arg0,
/// ::std::fmt::Display::fmt)],
/// }
/// ```
/// and that the type of `__arg0` is `&str` or `String`,
/// then returns the span of first element of the matched tuple.
fn get_single_string_arg<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<&'a Expr> {
    if_chain! {
        if let ExprKind::AddrOf(_, ref expr) = expr.node;
        if let ExprKind::Match(ref match_expr, ref arms, _) = expr.node;
        if arms.len() == 1;
        if arms[0].pats.len() == 1;
        if let PatKind::Tuple(ref pat, None) = arms[0].pats[0].node;
        if pat.len() == 1;
        if let ExprKind::Array(ref exprs) = arms[0].body.node;
        if exprs.len() == 1;
        if let ExprKind::Call(_, ref args) = exprs[0].node;
        if args.len() == 2;
        if let ExprKind::Path(ref qpath) = args[1].node;
        if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, args[1].hir_id));
        if match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD);
        then {
            let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0]));
            if ty.sty == ty::Str || match_type(cx, ty, &paths::STRING) {
                if let ExprKind::Tup(ref values) = match_expr.node {
                    return Some(&values[0]);
                }
            }
        }
    }

    None
}

/// Checks if the expression matches
/// ```rust,ignore
/// &[_ {
///    format: _ {
///         width: _::Implied,
///         ...
///    },
///    ...,
/// }]
/// ```
fn check_unformatted(expr: &Expr) -> bool {
    if_chain! {
        if let ExprKind::AddrOf(_, ref expr) = expr.node;
        if let ExprKind::Array(ref exprs) = expr.node;
        if exprs.len() == 1;
        if let ExprKind::Struct(_, ref fields, _) = exprs[0].node;
        if let Some(format_field) = fields.iter().find(|f| f.ident.name == "format");
        if let ExprKind::Struct(_, ref fields, _) = format_field.expr.node;
        if let Some(width_field) = fields.iter().find(|f| f.ident.name == "width");
        if let ExprKind::Path(ref width_qpath) = width_field.expr.node;
        if last_path_segment(width_qpath).ident.name == "Implied";
        if let Some(precision_field) = fields.iter().find(|f| f.ident.name == "precision");
        if let ExprKind::Path(ref precision_path) = precision_field.expr.node;
        if last_path_segment(precision_path).ident.name == "Implied";
        then {
            return true;
        }
    }

    false
}
<commit_msg>resolve build warnings in clippy_lints/src/format.rs<commit_after>use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use if_chain::if_chain;
use crate::rustc::ty;
use crate::syntax::ast::LitKind;
use crate::utils::paths;
use crate::utils::{in_macro, is_expn_of, last_path_segment, match_def_path, match_type, opt_def_id, resolve_node, snippet, span_lint_and_then, walk_ptrs_ty};
use crate::rustc_errors::Applicability;

/// **What it does:** Checks for the use of `format!("string literal with no
/// argument")` and `format!("{}", foo)` where `foo` is a string.
///
/// **Why is this bad?** There is no point of doing that. `format!("too")` can
/// be replaced by `"foo".to_owned()` if you really need a `String`. The even
/// worse `&format!("foo")` is often encountered in the wild. `format!("{}",
/// foo)` can be replaced by `foo.clone()` if `foo: String` or `foo.to_owned()`
/// if `foo: &str`.
///
/// **Known problems:** None.
///
/// **Examples:**
/// ```rust
/// format!("foo")
/// format!("{}", foo)
/// ```
declare_clippy_lint! {
    pub USELESS_FORMAT,
    complexity,
    "useless use of `format!`"
}

#[derive(Copy, Clone, Debug)]
pub struct Pass;

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array![USELESS_FORMAT]
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if let Some(span) = is_expn_of(expr.span, "format") {
            if in_macro(span) {
                return;
            }
            match expr.node {
                // `format!("{}", foo)` expansion
                ExprKind::Call(ref fun, ref args) => {
                    if_chain! {
                        if let ExprKind::Path(ref qpath) = fun.node;
                        if args.len() == 3;
                        if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id));
                        if match_def_path(cx.tcx, fun_def_id, &paths::FMT_ARGUMENTS_NEWV1FORMATTED);
                        if check_single_piece(&args[0]);
                        if let Some(format_arg) = get_single_string_arg(cx, &args[1]);
                        if check_unformatted(&args[2]);
                        if let ExprKind::AddrOf(_, ref format_arg) = format_arg.node;
                        then {
                            let (message, sugg) = if_chain! {
                                if let ExprKind::MethodCall(ref path, _, _) = format_arg.node;
                                if path.ident.as_interned_str() == "to_string";
                                then {
                                    ("`to_string()` is enough",
                                    snippet(cx, format_arg.span, "<arg>").to_string())
                                } else {
                                    ("consider using .to_string()",
                                    format!("{}.to_string()", snippet(cx, format_arg.span, "<arg>")))
                                }
                            };

                            span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| {
                                db.span_suggestion_with_applicability(
                                    expr.span,
                                    message,
                                    sugg,
                                    Applicability::MachineApplicable,
                                );
                            });
                        }
                    }
                },
                // `format!("foo")` expansion contains `match () { () => [], }`
                ExprKind::Match(ref matchee, _, _) => if let ExprKind::Tup(ref tup) = matchee.node {
                    if tup.is_empty() {
                        let sugg = format!("{}.to_string()", snippet(cx, expr.span, "<expr>").into_owned());
                        span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| {
                            db.span_suggestion_with_applicability(
                                span,
                                "consider using .to_string()",
                                sugg,
                                Applicability::MachineApplicable, // snippet
                            );
                        });
                    }
                },
                _ => (),
            }
        }
    }
}

/// Checks if the expressions matches `&[""]`
fn check_single_piece(expr: &Expr) -> bool {
    if_chain! {
        if let ExprKind::AddrOf(_, ref expr) = expr.node; // &[""]
        if let ExprKind::Array(ref exprs) = expr.node; // [""]
        if exprs.len() == 1;
        if let ExprKind::Lit(ref lit) = exprs[0].node;
        if let LitKind::Str(ref lit, _) = lit.node;
        then {
            return lit.as_str().is_empty();
        }
    }

    false
}

/// Checks if the expressions matches
/// ```rust,ignore
/// &match (&"arg",) {
/// (__arg0,) => [::std::fmt::ArgumentV1::new(__arg0,
/// ::std::fmt::Display::fmt)],
/// }
/// ```
/// and that the type of `__arg0` is `&str` or `String`,
/// then returns the span of first element of the matched tuple.
fn get_single_string_arg<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<&'a Expr> {
    if_chain! {
        if let ExprKind::AddrOf(_, ref expr) = expr.node;
        if let ExprKind::Match(ref match_expr, ref arms, _) = expr.node;
        if arms.len() == 1;
        if arms[0].pats.len() == 1;
        if let PatKind::Tuple(ref pat, None) = arms[0].pats[0].node;
        if pat.len() == 1;
        if let ExprKind::Array(ref exprs) = arms[0].body.node;
        if exprs.len() == 1;
        if let ExprKind::Call(_, ref args) = exprs[0].node;
        if args.len() == 2;
        if let ExprKind::Path(ref qpath) = args[1].node;
        if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, args[1].hir_id));
        if match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD);
        then {
            let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0]));
            if ty.sty == ty::Str || match_type(cx, ty, &paths::STRING) {
                if let ExprKind::Tup(ref values) = match_expr.node {
                    return Some(&values[0]);
                }
            }
        }
    }

    None
}

/// Checks if the expression matches
/// ```rust,ignore
/// &[_ {
///    format: _ {
///         width: _::Implied,
///         ...
///    },
///    ...,
/// }]
/// ```
fn check_unformatted(expr: &Expr) -> bool {
    if_chain! {
        if let ExprKind::AddrOf(_, ref expr) = expr.node;
        if let ExprKind::Array(ref exprs) = expr.node;
        if exprs.len() == 1;
        if let ExprKind::Struct(_, ref fields, _) = exprs[0].node;
        if let Some(format_field) = fields.iter().find(|f| f.ident.name == "format");
        if let ExprKind::Struct(_, ref fields, _) = format_field.expr.node;
        if let Some(width_field) = fields.iter().find(|f| f.ident.name == "width");
        if let ExprKind::Path(ref width_qpath) = width_field.expr.node;
        if last_path_segment(width_qpath).ident.name == "Implied";
        if let Some(precision_field) = fields.iter().find(|f| f.ident.name == "precision");
        if let ExprKind::Path(ref precision_path) = precision_field.expr.node;
        if last_path_segment(precision_path).ident.name == "Implied";
        then {
            return true;
        }
    }

    false
}
<|endoftext|>


<commit_before>use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then};
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
    Block, Body, Expr, ExprKind, FnDecl, Guard, HirId, Local, MutTy, Pat, PatKind, Path, QPath, StmtKind, Ty, TyKind,
    UnOp,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::symbol::Symbol;

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, while just changing reference level or mutability.
    ///
    /// **Why is this bad?** Not much, in fact it's a very common pattern in Rust
    /// code. Still, some may opt to avoid it in their code base, they can set this
    /// lint to `Warn`.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns.
    ///
    /// **Example:**
    /// ```rust
    /// # let x = 1;
    /// // Bad
    /// let x = &x;
    ///
    /// // Good
    /// let y = &x; // use different variable name
    /// ```
    pub SHADOW_SAME,
    restriction,
    "rebinding a name to itself, e.g., `let mut x = &mut x`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, while reusing the original value.
    ///
    /// **Why is this bad?** Not too much, in fact it's a common pattern in Rust
    /// code. Still, some argue that name shadowing like this hurts readability,
    /// because a value may be bound to different things depending on position in
    /// the code.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns.
    ///
    /// **Example:**
    /// ```rust
    /// let x = 2;
    /// let x = x + 1;
    /// ```
    /// use different variable name:
    /// ```rust
    /// let x = 2;
    /// let y = x + 1;
    /// ```
    pub SHADOW_REUSE,
    restriction,
    "rebinding a name to an expression that re-uses the original value, e.g., `let x = x + 1`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, either without a initialization or with one that does not even use
    /// the original value.
    ///
    /// **Why is this bad?** Name shadowing can hurt readability, especially in
    /// large code bases, because it is easy to lose track of the active binding at
    /// any place in the code. This can be alleviated by either giving more specific
    /// names to bindings or introducing more scopes to contain the bindings.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns.
    ///
    /// **Example:**
    /// ```rust
    /// # let y = 1;
    /// # let z = 2;
    /// let x = y;
    ///
    /// // Bad
    /// let x = z; // shadows the earlier binding
    ///
    /// // Good
    /// let w = z; // use different variable name
    /// ```
    pub SHADOW_UNRELATED,
    pedantic,
    "rebinding a name without even using the original value"
}

declare_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]);

impl<'tcx> LateLintPass<'tcx> for Shadow {
    fn check_fn(
        &mut self,
        cx: &LateContext<'tcx>,
        _: FnKind<'tcx>,
        decl: &'tcx FnDecl<'_>,
        body: &'tcx Body<'_>,
        _: Span,
        _: HirId,
    ) {
        if in_external_macro(cx.sess(), body.value.span) {
            return;
        }
        check_fn(cx, decl, body);
    }
}

fn check_fn<'tcx>(cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>) {
    let mut bindings = Vec::with_capacity(decl.inputs.len());
    for arg in iter_input_pats(decl, body) {
        if let PatKind::Binding(.., ident, _) = arg.pat.kind {
            bindings.push((ident.name, ident.span))
        }
    }
    check_expr(cx, &body.value, &mut bindings);
}

fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>, bindings: &mut Vec<(Symbol, Span)>) {
    let len = bindings.len();
    for stmt in block.stmts {
        match stmt.kind {
            StmtKind::Local(ref local) => check_local(cx, local, bindings),
            StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => check_expr(cx, e, bindings),
            StmtKind::Item(..) => {},
        }
    }
    if let Some(ref o) = block.expr {
        check_expr(cx, o, bindings);
    }
    bindings.truncate(len);
}

fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: &mut Vec<(Symbol, Span)>) {
    if in_external_macro(cx.sess(), local.span) {
        return;
    }
    if higher::is_from_for_desugar(local) {
        return;
    }
    let Local {
        ref pat,
        ref ty,
        ref init,
        span,
        ..
    } = *local;
    if let Some(ref t) = *ty {
        check_ty(cx, t, bindings)
    }
    if let Some(ref o) = *init {
        check_expr(cx, o, bindings);
        check_pat(cx, pat, Some(o), span, bindings);
    } else {
        check_pat(cx, pat, None, span, bindings);
    }
}

fn is_binding(cx: &LateContext<'_>, pat_id: HirId) -> bool {
    let var_ty = cx.typeck_results().node_type_opt(pat_id);
    var_ty.map_or(false, |var_ty| !matches!(var_ty.kind(), ty::Adt(..)))
}

fn check_pat<'tcx>(
    cx: &LateContext<'tcx>,
    pat: &'tcx Pat<'_>,
    init: Option<&'tcx Expr<'_>>,
    span: Span,
    bindings: &mut Vec<(Symbol, Span)>,
) {
    // TODO: match more stuff / destructuring
    match pat.kind {
        PatKind::Binding(.., ident, ref inner) => {
            let name = ident.name;
            if is_binding(cx, pat.hir_id) {
                let mut new_binding = true;
                for tup in bindings.iter_mut() {
                    if tup.0 == name {
                        lint_shadow(cx, name, span, pat.span, init, tup.1);
                        tup.1 = ident.span;
                        new_binding = false;
                        break;
                    }
                }
                if new_binding {
                    bindings.push((name, ident.span));
                }
            }
            if let Some(ref p) = *inner {
                check_pat(cx, p, init, span, bindings);
            }
        },
        PatKind::Struct(_, pfields, _) => {
            if let Some(init_struct) = init {
                if let ExprKind::Struct(_, ref efields, _) = init_struct.kind {
                    for field in pfields {
                        let name = field.ident.name;
                        let efield = efields
                            .iter()
                            .find_map(|f| if f.ident.name == name { Some(&*f.expr) } else { None });
                        check_pat(cx, &field.pat, efield, span, bindings);
                    }
                } else {
                    for field in pfields {
                        check_pat(cx, &field.pat, init, span, bindings);
                    }
                }
            } else {
                for field in pfields {
                    check_pat(cx, &field.pat, None, span, bindings);
                }
            }
        },
        PatKind::Tuple(inner, _) => {
            if let Some(init_tup) = init {
                if let ExprKind::Tup(ref tup) = init_tup.kind {
                    for (i, p) in inner.iter().enumerate() {
                        check_pat(cx, p, Some(&tup[i]), p.span, bindings);
                    }
                } else {
                    for p in inner {
                        check_pat(cx, p, init, span, bindings);
                    }
                }
            } else {
                for p in inner {
                    check_pat(cx, p, None, span, bindings);
                }
            }
        },
        PatKind::Box(ref inner) => {
            if let Some(initp) = init {
                if let ExprKind::Box(ref inner_init) = initp.kind {
                    check_pat(cx, inner, Some(&**inner_init), span, bindings);
                } else {
                    check_pat(cx, inner, init, span, bindings);
                }
            } else {
                check_pat(cx, inner, init, span, bindings);
            }
        },
        PatKind::Ref(ref inner, _) => check_pat(cx, inner, init, span, bindings),
        // PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
        _ => (),
    }
}

fn lint_shadow<'tcx>(
    cx: &LateContext<'tcx>,
    name: Symbol,
    span: Span,
    pattern_span: Span,
    init: Option<&'tcx Expr<'_>>,
    prev_span: Span,
) {
    if let Some(expr) = init {
        if is_self_shadow(name, expr) {
            span_lint_and_then(
                cx,
                SHADOW_SAME,
                span,
                &format!(
                    "`{}` is shadowed by itself in `{}`",
                    snippet(cx, pattern_span, "_"),
                    snippet(cx, expr.span, "..")
                ),
                |diag| {
                    diag.span_note(prev_span, "previous binding is here");
                },
            );
        } else if contains_name(name, expr) {
            span_lint_and_then(
                cx,
                SHADOW_REUSE,
                pattern_span,
                &format!(
                    "`{}` is shadowed by `{}` which reuses the original value",
                    snippet(cx, pattern_span, "_"),
                    snippet(cx, expr.span, "..")
                ),
                |diag| {
                    diag.span_note(expr.span, "initialization happens here");
                    diag.span_note(prev_span, "previous binding is here");
                },
            );
        } else {
            span_lint_and_then(
                cx,
                SHADOW_UNRELATED,
                pattern_span,
                &format!("`{}` is being shadowed", snippet(cx, pattern_span, "_")),
                |diag| {
                    diag.span_note(expr.span, "initialization happens here");
                    diag.span_note(prev_span, "previous binding is here");
                },
            );
        }
    } else {
        span_lint_and_then(
            cx,
            SHADOW_UNRELATED,
            span,
            &format!("`{}` shadows a previous declaration", snippet(cx, pattern_span, "_")),
            |diag| {
                diag.span_note(prev_span, "previous binding is here");
            },
        );
    }
}

fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut Vec<(Symbol, Span)>) {
    if in_external_macro(cx.sess(), expr.span) {
        return;
    }
    match expr.kind {
        ExprKind::Unary(_, ref e)
        | ExprKind::Field(ref e, _)
        | ExprKind::AddrOf(_, _, ref e)
        | ExprKind::Box(ref e) => check_expr(cx, e, bindings),
        ExprKind::Block(ref block, _) | ExprKind::Loop(ref block, _, _) => check_block(cx, block, bindings),
        // ExprKind::Call
        // ExprKind::MethodCall
        ExprKind::Array(v) | ExprKind::Tup(v) => {
            for e in v {
                check_expr(cx, e, bindings)
            }
        },
        ExprKind::Match(ref init, arms, _) => {
            check_expr(cx, init, bindings);
            let len = bindings.len();
            for arm in arms {
                check_pat(cx, &arm.pat, Some(&**init), arm.pat.span, bindings);
                // This is ugly, but needed to get the right type
                if let Some(ref guard) = arm.guard {
                    match guard {
                        Guard::If(if_expr) => check_expr(cx, if_expr, bindings),
                    }
                }
                check_expr(cx, &arm.body, bindings);
                bindings.truncate(len);
            }
        },
        _ => (),
    }
}

fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(Symbol, Span)>) {
    match ty.kind {
        TyKind::Slice(ref sty) => check_ty(cx, sty, bindings),
        TyKind::Array(ref fty, ref anon_const) => {
            check_ty(cx, fty, bindings);
            check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings);
        },
        TyKind::Ptr(MutTy { ty: ref mty, .. }) | TyKind::Rptr(_, MutTy { ty: ref mty, .. }) => {
            check_ty(cx, mty, bindings)
        },
        TyKind::Tup(tup) => {
            for t in tup {
                check_ty(cx, t, bindings)
            }
        },
        TyKind::Typeof(ref anon_const) => check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings),
        _ => (),
    }
}

fn is_self_shadow(name: Symbol, expr: &Expr<'_>) -> bool {
    match expr.kind {
        ExprKind::Box(ref inner) | ExprKind::AddrOf(_, _, ref inner) => is_self_shadow(name, inner),
        ExprKind::Block(ref block, _) => {
            block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e))
        },
        ExprKind::Unary(op, ref inner) => (UnOp::UnDeref == op) && is_self_shadow(name, inner),
        ExprKind::Path(QPath::Resolved(_, ref path)) => path_eq_name(name, path),
        _ => false,
    }
}

fn path_eq_name(name: Symbol, path: &Path<'_>) -> bool {
    !path.is_global() && path.segments.len() == 1 && path.segments[0].ident.as_str() == name.as_str()
}
<commit_msg>Add note to `shadow_unrelated`<commit_after>use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then};
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
    Block, Body, Expr, ExprKind, FnDecl, Guard, HirId, Local, MutTy, Pat, PatKind, Path, QPath, StmtKind, Ty, TyKind,
    UnOp,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::symbol::Symbol;

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, while just changing reference level or mutability.
    ///
    /// **Why is this bad?** Not much, in fact it's a very common pattern in Rust
    /// code. Still, some may opt to avoid it in their code base, they can set this
    /// lint to `Warn`.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns.
    ///
    /// **Example:**
    /// ```rust
    /// # let x = 1;
    /// // Bad
    /// let x = &x;
    ///
    /// // Good
    /// let y = &x; // use different variable name
    /// ```
    pub SHADOW_SAME,
    restriction,
    "rebinding a name to itself, e.g., `let mut x = &mut x`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, while reusing the original value.
    ///
    /// **Why is this bad?** Not too much, in fact it's a common pattern in Rust
    /// code. Still, some argue that name shadowing like this hurts readability,
    /// because a value may be bound to different things depending on position in
    /// the code.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns.
    ///
    /// **Example:**
    /// ```rust
    /// let x = 2;
    /// let x = x + 1;
    /// ```
    /// use different variable name:
    /// ```rust
    /// let x = 2;
    /// let y = x + 1;
    /// ```
    pub SHADOW_REUSE,
    restriction,
    "rebinding a name to an expression that re-uses the original value, e.g., `let x = x + 1`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, either without a initialization or with one that does not even use
    /// the original value.
    ///
    /// **Why is this bad?** Name shadowing can hurt readability, especially in
    /// large code bases, because it is easy to lose track of the active binding at
    /// any place in the code. This can be alleviated by either giving more specific
    /// names to bindings or introducing more scopes to contain the bindings.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns. Note that
    /// `allow`/`warn`/`deny`/`forbid` attributes only work on the function level
    /// for this lint.
    ///
    /// **Example:**
    /// ```rust
    /// # let y = 1;
    /// # let z = 2;
    /// let x = y;
    ///
    /// // Bad
    /// let x = z; // shadows the earlier binding
    ///
    /// // Good
    /// let w = z; // use different variable name
    /// ```
    pub SHADOW_UNRELATED,
    pedantic,
    "rebinding a name without even using the original value"
}

declare_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]);

impl<'tcx> LateLintPass<'tcx> for Shadow {
    fn check_fn(
        &mut self,
        cx: &LateContext<'tcx>,
        _: FnKind<'tcx>,
        decl: &'tcx FnDecl<'_>,
        body: &'tcx Body<'_>,
        _: Span,
        _: HirId,
    ) {
        if in_external_macro(cx.sess(), body.value.span) {
            return;
        }
        check_fn(cx, decl, body);
    }
}

fn check_fn<'tcx>(cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>) {
    let mut bindings = Vec::with_capacity(decl.inputs.len());
    for arg in iter_input_pats(decl, body) {
        if let PatKind::Binding(.., ident, _) = arg.pat.kind {
            bindings.push((ident.name, ident.span))
        }
    }
    check_expr(cx, &body.value, &mut bindings);
}

fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>, bindings: &mut Vec<(Symbol, Span)>) {
    let len = bindings.len();
    for stmt in block.stmts {
        match stmt.kind {
            StmtKind::Local(ref local) => check_local(cx, local, bindings),
            StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => check_expr(cx, e, bindings),
            StmtKind::Item(..) => {},
        }
    }
    if let Some(ref o) = block.expr {
        check_expr(cx, o, bindings);
    }
    bindings.truncate(len);
}

fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: &mut Vec<(Symbol, Span)>) {
    if in_external_macro(cx.sess(), local.span) {
        return;
    }
    if higher::is_from_for_desugar(local) {
        return;
    }
    let Local {
        ref pat,
        ref ty,
        ref init,
        span,
        ..
    } = *local;
    if let Some(ref t) = *ty {
        check_ty(cx, t, bindings)
    }
    if let Some(ref o) = *init {
        check_expr(cx, o, bindings);
        check_pat(cx, pat, Some(o), span, bindings);
    } else {
        check_pat(cx, pat, None, span, bindings);
    }
}

fn is_binding(cx: &LateContext<'_>, pat_id: HirId) -> bool {
    let var_ty = cx.typeck_results().node_type_opt(pat_id);
    var_ty.map_or(false, |var_ty| !matches!(var_ty.kind(), ty::Adt(..)))
}

fn check_pat<'tcx>(
    cx: &LateContext<'tcx>,
    pat: &'tcx Pat<'_>,
    init: Option<&'tcx Expr<'_>>,
    span: Span,
    bindings: &mut Vec<(Symbol, Span)>,
) {
    // TODO: match more stuff / destructuring
    match pat.kind {
        PatKind::Binding(.., ident, ref inner) => {
            let name = ident.name;
            if is_binding(cx, pat.hir_id) {
                let mut new_binding = true;
                for tup in bindings.iter_mut() {
                    if tup.0 == name {
                        lint_shadow(cx, name, span, pat.span, init, tup.1);
                        tup.1 = ident.span;
                        new_binding = false;
                        break;
                    }
                }
                if new_binding {
                    bindings.push((name, ident.span));
                }
            }
            if let Some(ref p) = *inner {
                check_pat(cx, p, init, span, bindings);
            }
        },
        PatKind::Struct(_, pfields, _) => {
            if let Some(init_struct) = init {
                if let ExprKind::Struct(_, ref efields, _) = init_struct.kind {
                    for field in pfields {
                        let name = field.ident.name;
                        let efield = efields
                            .iter()
                            .find_map(|f| if f.ident.name == name { Some(&*f.expr) } else { None });
                        check_pat(cx, &field.pat, efield, span, bindings);
                    }
                } else {
                    for field in pfields {
                        check_pat(cx, &field.pat, init, span, bindings);
                    }
                }
            } else {
                for field in pfields {
                    check_pat(cx, &field.pat, None, span, bindings);
                }
            }
        },
        PatKind::Tuple(inner, _) => {
            if let Some(init_tup) = init {
                if let ExprKind::Tup(ref tup) = init_tup.kind {
                    for (i, p) in inner.iter().enumerate() {
                        check_pat(cx, p, Some(&tup[i]), p.span, bindings);
                    }
                } else {
                    for p in inner {
                        check_pat(cx, p, init, span, bindings);
                    }
                }
            } else {
                for p in inner {
                    check_pat(cx, p, None, span, bindings);
                }
            }
        },
        PatKind::Box(ref inner) => {
            if let Some(initp) = init {
                if let ExprKind::Box(ref inner_init) = initp.kind {
                    check_pat(cx, inner, Some(&**inner_init), span, bindings);
                } else {
                    check_pat(cx, inner, init, span, bindings);
                }
            } else {
                check_pat(cx, inner, init, span, bindings);
            }
        },
        PatKind::Ref(ref inner, _) => check_pat(cx, inner, init, span, bindings),
        // PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
        _ => (),
    }
}

fn lint_shadow<'tcx>(
    cx: &LateContext<'tcx>,
    name: Symbol,
    span: Span,
    pattern_span: Span,
    init: Option<&'tcx Expr<'_>>,
    prev_span: Span,
) {
    if let Some(expr) = init {
        if is_self_shadow(name, expr) {
            span_lint_and_then(
                cx,
                SHADOW_SAME,
                span,
                &format!(
                    "`{}` is shadowed by itself in `{}`",
                    snippet(cx, pattern_span, "_"),
                    snippet(cx, expr.span, "..")
                ),
                |diag| {
                    diag.span_note(prev_span, "previous binding is here");
                },
            );
        } else if contains_name(name, expr) {
            span_lint_and_then(
                cx,
                SHADOW_REUSE,
                pattern_span,
                &format!(
                    "`{}` is shadowed by `{}` which reuses the original value",
                    snippet(cx, pattern_span, "_"),
                    snippet(cx, expr.span, "..")
                ),
                |diag| {
                    diag.span_note(expr.span, "initialization happens here");
                    diag.span_note(prev_span, "previous binding is here");
                },
            );
        } else {
            span_lint_and_then(
                cx,
                SHADOW_UNRELATED,
                pattern_span,
                &format!("`{}` is being shadowed", snippet(cx, pattern_span, "_")),
                |diag| {
                    diag.span_note(expr.span, "initialization happens here");
                    diag.span_note(prev_span, "previous binding is here");
                },
            );
        }
    } else {
        span_lint_and_then(
            cx,
            SHADOW_UNRELATED,
            span,
            &format!("`{}` shadows a previous declaration", snippet(cx, pattern_span, "_")),
            |diag| {
                diag.span_note(prev_span, "previous binding is here");
            },
        );
    }
}

fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut Vec<(Symbol, Span)>) {
    if in_external_macro(cx.sess(), expr.span) {
        return;
    }
    match expr.kind {
        ExprKind::Unary(_, ref e)
        | ExprKind::Field(ref e, _)
        | ExprKind::AddrOf(_, _, ref e)
        | ExprKind::Box(ref e) => check_expr(cx, e, bindings),
        ExprKind::Block(ref block, _) | ExprKind::Loop(ref block, _, _) => check_block(cx, block, bindings),
        // ExprKind::Call
        // ExprKind::MethodCall
        ExprKind::Array(v) | ExprKind::Tup(v) => {
            for e in v {
                check_expr(cx, e, bindings)
            }
        },
        ExprKind::Match(ref init, arms, _) => {
            check_expr(cx, init, bindings);
            let len = bindings.len();
            for arm in arms {
                check_pat(cx, &arm.pat, Some(&**init), arm.pat.span, bindings);
                // This is ugly, but needed to get the right type
                if let Some(ref guard) = arm.guard {
                    match guard {
                        Guard::If(if_expr) => check_expr(cx, if_expr, bindings),
                    }
                }
                check_expr(cx, &arm.body, bindings);
                bindings.truncate(len);
            }
        },
        _ => (),
    }
}

fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(Symbol, Span)>) {
    match ty.kind {
        TyKind::Slice(ref sty) => check_ty(cx, sty, bindings),
        TyKind::Array(ref fty, ref anon_const) => {
            check_ty(cx, fty, bindings);
            check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings);
        },
        TyKind::Ptr(MutTy { ty: ref mty, .. }) | TyKind::Rptr(_, MutTy { ty: ref mty, .. }) => {
            check_ty(cx, mty, bindings)
        },
        TyKind::Tup(tup) => {
            for t in tup {
                check_ty(cx, t, bindings)
            }
        },
        TyKind::Typeof(ref anon_const) => check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings),
        _ => (),
    }
}

fn is_self_shadow(name: Symbol, expr: &Expr<'_>) -> bool {
    match expr.kind {
        ExprKind::Box(ref inner) | ExprKind::AddrOf(_, _, ref inner) => is_self_shadow(name, inner),
        ExprKind::Block(ref block, _) => {
            block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e))
        },
        ExprKind::Unary(op, ref inner) => (UnOp::UnDeref == op) && is_self_shadow(name, inner),
        ExprKind::Path(QPath::Resolved(_, ref path)) => path_eq_name(name, path),
        _ => false,
    }
}

fn path_eq_name(name: Symbol, path: &Path<'_>) -> bool {
    !path.is_global() && path.segments.len() == 1 && path.segments[0].ident.as_str() == name.as_str()
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//#![feature(mpsc_select)]

//! A GPU based Webrender.
//!
//! It serves as an experimental render backend for [Servo](https://servo.org/),
//! but it can also be used as such in a standalone application.
//!
//! # External dependencies
//! Webrender currently depends on [FreeType](https://www.freetype.org/)
//!
//! # Api Structure
//! The main entry point to webrender is the `webrender::renderer::Renderer`.
//!
//! By calling `Renderer::new(...)` you get a `Renderer`, as well as a `RenderApiSender`.
//! Your `Renderer` is responsible to render the previously processed frames onto the screen.
//!
//! By calling `yourRenderApiSenderInstance.create_api()`, you'll get a `RenderApi` instance,
//! which is responsible for the processing of new frames. A worker thread is used internally to
//! untie the workload from the application thread and therefore be able
//! to make better use of multicore systems.
//!
//! What is referred to as a `frame`, is the current geometry on the screen.
//! A new Frame is created by calling [`set_root_display_list()`][newframe] on the `RenderApi`.
//! When the geometry is processed, the application will be informed via a `RenderNotifier`,
//! a callback which you employ with [set_render_notifier][notifier] on the `Renderer`
//! More information about [stacking contexts][stacking_contexts].
//!
//! `set_root_display_list()` also needs to be supplied with `BuiltDisplayList`s.
//! These are obtained by finalizing a `DisplayListBuilder`. These are used to draw your geometry.
//! But it doesn't only contain trivial geometry, it can also store another StackingContext, as
//! they're nestable.
//!
//! [stacking_contexts]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
//! [newframe]: ../webrender_traits/struct.RenderApi.html#method.set_root_display_list
//! [notifier]: renderer/struct.Renderer.html#method.set_render_notifier

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate thread_profiler;

mod batch_builder;
mod clip_scroll_node;
mod clip_scroll_tree;
mod debug_colors;
mod debug_font_data;
mod debug_render;
mod device;
mod frame;
mod frame_builder;
mod freelist;
mod geometry;
mod gpu_store;
mod internal_types;
mod mask_cache;
mod prim_store;
mod profiler;
mod record;
mod render_backend;
mod render_task;
mod resource_cache;
mod scene;
mod spring;
mod texture_cache;
mod tiling;
mod util;

#[cfg(feature = "webgl")]
mod webgl_types;

#[cfg(not(feature = "webgl"))]
#[path = "webgl_stubs.rs"]
mod webgl_types;

mod shader_source {
    include!(concat!(env!("OUT_DIR"), "/shaders.rs"));
}

pub use record::{ApiRecordingReceiver, BinaryRecorder, WEBRENDER_RECORDING_HEADER};

mod platform {
    #[cfg(target_os="macos")]
    pub use platform::macos::font;
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub use platform::unix::font;
    #[cfg(target_os = "windows")]
    pub use platform::windows::font;

    #[cfg(target_os="macos")]
    pub mod macos {
        pub mod font;
    }
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub mod unix {
        pub mod font;
    }
    #[cfg(target_os = "windows")]
    pub mod windows {
        pub mod font;
    }
}

pub mod renderer;

#[cfg(target_os="macos")]
extern crate core_graphics;
#[cfg(target_os="macos")]
extern crate core_text;

#[cfg(all(unix, not(target_os="macos")))]
extern crate freetype;

#[cfg(target_os = "windows")]
extern crate dwrote;

extern crate app_units;
extern crate bincode;
extern crate euclid;
extern crate fnv;
extern crate gleam;
extern crate num_traits;
//extern crate notify;
extern crate time;
extern crate webrender_traits;
#[cfg(feature = "webgl")]
extern crate offscreen_gl_context;
extern crate byteorder;
extern crate threadpool;

#[cfg(any(target_os="macos", target_os="windows"))]
extern crate gamma_lut;

pub use renderer::{ExternalImage, ExternalImageSource, ExternalImageHandler};
pub use renderer::{Renderer, RendererOptions};
<commit_msg>Auto merge of #1052 - waywardmonkeys:remove-commented-out-feature, r=glennw<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A GPU based Webrender.
//!
//! It serves as an experimental render backend for [Servo](https://servo.org/),
//! but it can also be used as such in a standalone application.
//!
//! # External dependencies
//! Webrender currently depends on [FreeType](https://www.freetype.org/)
//!
//! # Api Structure
//! The main entry point to webrender is the `webrender::renderer::Renderer`.
//!
//! By calling `Renderer::new(...)` you get a `Renderer`, as well as a `RenderApiSender`.
//! Your `Renderer` is responsible to render the previously processed frames onto the screen.
//!
//! By calling `yourRenderApiSenderInstance.create_api()`, you'll get a `RenderApi` instance,
//! which is responsible for the processing of new frames. A worker thread is used internally to
//! untie the workload from the application thread and therefore be able
//! to make better use of multicore systems.
//!
//! What is referred to as a `frame`, is the current geometry on the screen.
//! A new Frame is created by calling [`set_root_display_list()`][newframe] on the `RenderApi`.
//! When the geometry is processed, the application will be informed via a `RenderNotifier`,
//! a callback which you employ with [set_render_notifier][notifier] on the `Renderer`
//! More information about [stacking contexts][stacking_contexts].
//!
//! `set_root_display_list()` also needs to be supplied with `BuiltDisplayList`s.
//! These are obtained by finalizing a `DisplayListBuilder`. These are used to draw your geometry.
//! But it doesn't only contain trivial geometry, it can also store another StackingContext, as
//! they're nestable.
//!
//! [stacking_contexts]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
//! [newframe]: ../webrender_traits/struct.RenderApi.html#method.set_root_display_list
//! [notifier]: renderer/struct.Renderer.html#method.set_render_notifier

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate thread_profiler;

mod batch_builder;
mod clip_scroll_node;
mod clip_scroll_tree;
mod debug_colors;
mod debug_font_data;
mod debug_render;
mod device;
mod frame;
mod frame_builder;
mod freelist;
mod geometry;
mod gpu_store;
mod internal_types;
mod mask_cache;
mod prim_store;
mod profiler;
mod record;
mod render_backend;
mod render_task;
mod resource_cache;
mod scene;
mod spring;
mod texture_cache;
mod tiling;
mod util;

#[cfg(feature = "webgl")]
mod webgl_types;

#[cfg(not(feature = "webgl"))]
#[path = "webgl_stubs.rs"]
mod webgl_types;

mod shader_source {
    include!(concat!(env!("OUT_DIR"), "/shaders.rs"));
}

pub use record::{ApiRecordingReceiver, BinaryRecorder, WEBRENDER_RECORDING_HEADER};

mod platform {
    #[cfg(target_os="macos")]
    pub use platform::macos::font;
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub use platform::unix::font;
    #[cfg(target_os = "windows")]
    pub use platform::windows::font;

    #[cfg(target_os="macos")]
    pub mod macos {
        pub mod font;
    }
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub mod unix {
        pub mod font;
    }
    #[cfg(target_os = "windows")]
    pub mod windows {
        pub mod font;
    }
}

pub mod renderer;

#[cfg(target_os="macos")]
extern crate core_graphics;
#[cfg(target_os="macos")]
extern crate core_text;

#[cfg(all(unix, not(target_os="macos")))]
extern crate freetype;

#[cfg(target_os = "windows")]
extern crate dwrote;

extern crate app_units;
extern crate bincode;
extern crate euclid;
extern crate fnv;
extern crate gleam;
extern crate num_traits;
//extern crate notify;
extern crate time;
extern crate webrender_traits;
#[cfg(feature = "webgl")]
extern crate offscreen_gl_context;
extern crate byteorder;
extern crate threadpool;

#[cfg(any(target_os="macos", target_os="windows"))]
extern crate gamma_lut;

pub use renderer::{ExternalImage, ExternalImageSource, ExternalImageHandler};
pub use renderer::{Renderer, RendererOptions};
<|endoftext|>


<commit_before>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use ffi;
use translate::*;
use std::mem;
use std::mem::transmute;
use ffi as glib_ffi;
use ffi::{gpointer, gboolean};

use MainContext;
use Source;
use SourceId;

use source::{CallbackGuard, Priority};

impl MainContext {
    pub fn prepare(&self) -> (bool, i32) {
        unsafe {
            let mut priority = mem::uninitialized();

            let res = from_glib(ffi::g_main_context_prepare(self.to_glib_none().0, &mut priority));

            (res, priority)
        }
    }

    pub fn find_source_by_id(&self, source_id: SourceId) -> Option<Source> {
        unsafe {
            from_glib_none(ffi::g_main_context_find_source_by_id(self.to_glib_none().0, source_id.to_glib()))
        }
    }

    pub fn invoke<F>(&self, func: F)
    where F: FnOnce() + Send + 'static {
        unsafe {
            let func = Box::into_raw(Box::new(Some(Box::new(func))));
            glib_ffi::g_main_context_invoke_full(self.to_glib_none().0, glib_ffi::G_PRIORITY_DEFAULT_IDLE, Some(trampoline::<F>),
                func as gpointer, Some(destroy_closure::<F>))
        }
    }

    pub fn invoke_with_priority<F>(&self, priority: Priority, func: F)
    where F: FnOnce() + Send + 'static {
        unsafe {
            let func = Box::into_raw(Box::new(Some(Box::new(func))));
            glib_ffi::g_main_context_invoke_full(self.to_glib_none().0, priority.to_glib(), Some(trampoline::<F>),
                func as gpointer, Some(destroy_closure::<F>))
        }
    }
}

#[cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ref))]
unsafe extern "C" fn trampoline<F: FnOnce() + Send + 'static>(func: gpointer) -> gboolean {
    let _guard = CallbackGuard::new();
    let func: &mut Option<Box<F>> = transmute(func);
    let func = func.take().expect("MainContext::invoke() closure called multiple times");
    func();
    glib_ffi::G_SOURCE_REMOVE
}

unsafe extern "C" fn destroy_closure<F: FnOnce() + Send + 'static>(ptr: gpointer) {
    let _guard = CallbackGuard::new();
    Box::<Option<Box<F>>>::from_raw(ptr as *mut _);
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::thread;

    #[test]
    fn test_invoke() {
        let l = ::MainLoop::new(None, false);
        let c = MainContext::default().unwrap();

        let l_clone = l.clone();
        thread::spawn(move || {
            c.invoke(move || l_clone.quit());
        });

        l.run();
    }
}
<commit_msg>Make MainContext::invoke() just call invoke_with_priority() instead of duplicating code<commit_after>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use ffi;
use translate::*;
use std::mem;
use std::mem::transmute;
use ffi as glib_ffi;
use ffi::{gpointer, gboolean};

use MainContext;
use Source;
use SourceId;

use source::{CallbackGuard, Priority};

impl MainContext {
    pub fn prepare(&self) -> (bool, i32) {
        unsafe {
            let mut priority = mem::uninitialized();

            let res = from_glib(ffi::g_main_context_prepare(self.to_glib_none().0, &mut priority));

            (res, priority)
        }
    }

    pub fn find_source_by_id(&self, source_id: SourceId) -> Option<Source> {
        unsafe {
            from_glib_none(ffi::g_main_context_find_source_by_id(self.to_glib_none().0, source_id.to_glib()))
        }
    }

    pub fn invoke<F>(&self, func: F)
    where F: FnOnce() + Send + 'static {
        self.invoke_with_priority(::PRIORITY_DEFAULT_IDLE, func);
    }

    pub fn invoke_with_priority<F>(&self, priority: Priority, func: F)
    where F: FnOnce() + Send + 'static {
        unsafe {
            let func = Box::into_raw(Box::new(Some(Box::new(func))));
            glib_ffi::g_main_context_invoke_full(self.to_glib_none().0, priority.to_glib(), Some(trampoline::<F>),
                func as gpointer, Some(destroy_closure::<F>))
        }
    }
}

#[cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ref))]
unsafe extern "C" fn trampoline<F: FnOnce() + Send + 'static>(func: gpointer) -> gboolean {
    let _guard = CallbackGuard::new();
    let func: &mut Option<Box<F>> = transmute(func);
    let func = func.take().expect("MainContext::invoke() closure called multiple times");
    func();
    glib_ffi::G_SOURCE_REMOVE
}

unsafe extern "C" fn destroy_closure<F: FnOnce() + Send + 'static>(ptr: gpointer) {
    let _guard = CallbackGuard::new();
    Box::<Option<Box<F>>>::from_raw(ptr as *mut _);
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::thread;

    #[test]
    fn test_invoke() {
        let l = ::MainLoop::new(None, false);
        let c = MainContext::default().unwrap();

        let l_clone = l.clone();
        thread::spawn(move || {
            c.invoke(move || l_clone.quit());
        });

        l.run();
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 The Tink-Rust Authors
//
// 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,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

//! AES-GCM based implementation of the [`tink_core::Aead`] trait.

use aes_gcm::aead::{consts::U12, generic_array::GenericArray, Aead, NewAead, Payload};
use tink_core::{utils::wrap_err, TinkError};

/// The only IV size that this implementation supports.
pub const AES_GCM_IV_SIZE: usize = 12;
/// The only tag size that this implementation supports.
pub const AES_GCM_TAG_SIZE: usize = 16;
/// The maximum supported plaintext size.
const MAX_AES_GCM_PLAINTEXT_SIZE: usize = (1 << 36) - 32;

#[derive(Clone)]
enum AesGcmVariant {
    Aes128(Box<aes_gcm::Aes128Gcm>),
    Aes256(Box<aes_gcm::Aes256Gcm>),
}

/// `AesGcm` is an implementation of the [`tink_core::Aead`] trait.
#[derive(Clone)]
pub struct AesGcm {
    key: AesGcmVariant,
}

impl AesGcm {
    /// Return an [`AesGcm`] instance.
    /// The key argument should be the AES key, either 16 or 32 bytes to select
    /// AES-128 or AES-256.
    pub fn new(key: &[u8]) -> Result<AesGcm, TinkError> {
        let key = match key.len() {
            16 => AesGcmVariant::Aes128(Box::new(aes_gcm::Aes128Gcm::new(
                GenericArray::from_slice(key),
            ))),
            32 => AesGcmVariant::Aes256(Box::new(aes_gcm::Aes256Gcm::new(
                GenericArray::from_slice(key),
            ))),
            l => return Err(format!("AesGcm: invalid AES key size {} (want 16, 32)", l).into()),
        };
        Ok(AesGcm { key })
    }
}

impl tink_core::Aead for AesGcm {
    /// Encrypt `pt` with `aad` as additional authenticated data.  The resulting ciphertext consists
    /// of two parts: (1) the IV used for encryption and (2) the actual ciphertext.
    ///
    /// Note: AES-GCM implementation of crypto library always returns ciphertext with 128-bit tag.
    fn encrypt(&self, pt: &[u8], aad: &[u8]) -> Result<Vec<u8>, TinkError> {
        if pt.len() > max_pt_size() {
            return Err("AesGcm: plaintext too long".into());
        }
        let iv = new_iv();
        let payload = Payload { msg: pt, aad };
        let ct = match &self.key {
            AesGcmVariant::Aes128(key) => key.encrypt(&iv, payload),
            AesGcmVariant::Aes256(key) => key.encrypt(&iv, payload),
        }
        .map_err(|e| wrap_err("AesGcm", e))?;
        let mut ret = Vec::with_capacity(iv.len() + ct.len());
        ret.extend_from_slice(&iv);
        ret.extend_from_slice(&ct);
        Ok(ret)
    }

    /// Decrypt `ct` with `aad` as the additional authenticated data.
    fn decrypt(&self, ct: &[u8], aad: &[u8]) -> Result<Vec<u8>, TinkError> {
        if ct.len() < AES_GCM_IV_SIZE + AES_GCM_TAG_SIZE {
            return Err("AesGcm: ciphertext too short".into());
        }
        let iv = GenericArray::from_slice(&ct[..AES_GCM_IV_SIZE]);
        let payload = Payload {
            msg: &ct[AES_GCM_IV_SIZE..],
            aad,
        };
        let pt = match &self.key {
            AesGcmVariant::Aes128(key) => key.decrypt(iv, payload),
            AesGcmVariant::Aes256(key) => key.decrypt(iv, payload),
        }
        .map_err(|e| wrap_err("AesGcm", e))?;
        Ok(pt)
    }
}

/// Create a new IV for encryption.
fn new_iv() -> GenericArray<u8, U12> {
    let iv = tink_core::subtle::random::get_random_bytes(AES_GCM_IV_SIZE);
    *GenericArray::<u8, U12>::from_slice(&iv)
}

/// Maximum plaintext size.
fn max_pt_size() -> usize {
    let x = (isize::MAX as usize) - AES_GCM_IV_SIZE - AES_GCM_TAG_SIZE;
    std::cmp::min(x, MAX_AES_GCM_PLAINTEXT_SIZE)
}
<commit_msg>tink-aead: use u64 for max size calculation<commit_after>// Copyright 2020 The Tink-Rust Authors
//
// 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,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

//! AES-GCM based implementation of the [`tink_core::Aead`] trait.

use aes_gcm::aead::{consts::U12, generic_array::GenericArray, Aead, NewAead, Payload};
use tink_core::{utils::wrap_err, TinkError};

/// The only IV size that this implementation supports.
pub const AES_GCM_IV_SIZE: usize = 12;
/// The only tag size that this implementation supports.
pub const AES_GCM_TAG_SIZE: usize = 16;
/// The maximum supported plaintext size.
const MAX_AES_GCM_PLAINTEXT_SIZE: u64 = (1 << 36) - 32;

#[derive(Clone)]
enum AesGcmVariant {
    Aes128(Box<aes_gcm::Aes128Gcm>),
    Aes256(Box<aes_gcm::Aes256Gcm>),
}

/// `AesGcm` is an implementation of the [`tink_core::Aead`] trait.
#[derive(Clone)]
pub struct AesGcm {
    key: AesGcmVariant,
}

impl AesGcm {
    /// Return an [`AesGcm`] instance.
    /// The key argument should be the AES key, either 16 or 32 bytes to select
    /// AES-128 or AES-256.
    pub fn new(key: &[u8]) -> Result<AesGcm, TinkError> {
        let key = match key.len() {
            16 => AesGcmVariant::Aes128(Box::new(aes_gcm::Aes128Gcm::new(
                GenericArray::from_slice(key),
            ))),
            32 => AesGcmVariant::Aes256(Box::new(aes_gcm::Aes256Gcm::new(
                GenericArray::from_slice(key),
            ))),
            l => return Err(format!("AesGcm: invalid AES key size {} (want 16, 32)", l).into()),
        };
        Ok(AesGcm { key })
    }
}

impl tink_core::Aead for AesGcm {
    /// Encrypt `pt` with `aad` as additional authenticated data.  The resulting ciphertext consists
    /// of two parts: (1) the IV used for encryption and (2) the actual ciphertext.
    ///
    /// Note: AES-GCM implementation of crypto library always returns ciphertext with 128-bit tag.
    fn encrypt(&self, pt: &[u8], aad: &[u8]) -> Result<Vec<u8>, TinkError> {
        if pt.len() as u64 > max_pt_size() {
            return Err("AesGcm: plaintext too long".into());
        }
        let iv = new_iv();
        let payload = Payload { msg: pt, aad };
        let ct = match &self.key {
            AesGcmVariant::Aes128(key) => key.encrypt(&iv, payload),
            AesGcmVariant::Aes256(key) => key.encrypt(&iv, payload),
        }
        .map_err(|e| wrap_err("AesGcm", e))?;
        let mut ret = Vec::with_capacity(iv.len() + ct.len());
        ret.extend_from_slice(&iv);
        ret.extend_from_slice(&ct);
        Ok(ret)
    }

    /// Decrypt `ct` with `aad` as the additional authenticated data.
    fn decrypt(&self, ct: &[u8], aad: &[u8]) -> Result<Vec<u8>, TinkError> {
        if ct.len() < AES_GCM_IV_SIZE + AES_GCM_TAG_SIZE {
            return Err("AesGcm: ciphertext too short".into());
        }
        let iv = GenericArray::from_slice(&ct[..AES_GCM_IV_SIZE]);
        let payload = Payload {
            msg: &ct[AES_GCM_IV_SIZE..],
            aad,
        };
        let pt = match &self.key {
            AesGcmVariant::Aes128(key) => key.decrypt(iv, payload),
            AesGcmVariant::Aes256(key) => key.decrypt(iv, payload),
        }
        .map_err(|e| wrap_err("AesGcm", e))?;
        Ok(pt)
    }
}

/// Create a new IV for encryption.
fn new_iv() -> GenericArray<u8, U12> {
    let iv = tink_core::subtle::random::get_random_bytes(AES_GCM_IV_SIZE);
    *GenericArray::<u8, U12>::from_slice(&iv)
}

/// Maximum plaintext size.
///  - 32-bit platform: (2^31 - 1) - 12 - 16
///  - 64-bit platform: 2^36 - 32
const fn max_pt_size() -> u64 {
    let x: usize = (isize::MAX as usize) - AES_GCM_IV_SIZE - AES_GCM_TAG_SIZE;
    let x: u64 = x as u64;
    if x > MAX_AES_GCM_PLAINTEXT_SIZE {
        MAX_AES_GCM_PLAINTEXT_SIZE
    } else {
        x
    }
}
<|endoftext|>


<commit_before>// -*-  indent-tabs-mode:nil; tab-width:2;  -*-
extern crate random;
extern crate tensorflow;

use random::Source;
use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::result::Result;
use std::path::Path;
use std::process::exit;
use tensorflow::Code;
use tensorflow::Session;
use tensorflow::SessionOptions;
use tensorflow::Status;
use tensorflow::Step;
use tensorflow::Tensor;

fn main() {
  // Putting the main code in another function serves two purposes:
  // 1. We can use the try! macro.
  // 2. We can call exit safely, which does not run any destructors.
  exit(match run() {
    Ok(_) => 0,
    Err(e) => {
      println!("{}", e);
      1
    }
  })
}

fn run() -> Result<(), Box<Error>> {
  let filename = "regression-model/model.pb"; // y = w * x + b
  if !Path::new(filename).exists() {
    return Err(Box::new(Status::new_set(Code::NotFound, &format!(
      "Run 'python regression.py' to generate {} and try again.", filename)).unwrap()));
  }

  // Generate some test data.
  let w = 0.1;
  let b = 0.3;
  let num_points = 100;
  let steps = 201;
  let mut rand = random::default();
  let mut x = Tensor::new(&[num_points as u64]);
  let mut y = Tensor::new(&[num_points as u64]);
  for i in 0..num_points {
    x[i] = (2.0 * rand.read::<f64>() - 1.0) as f32;
    y[i] = w * x[i] + b;
  }

  // Load the computation graph defined by regression.py.
  let mut session = try!(Session::new(&SessionOptions::new()));
  let mut proto = Vec::new();
  try!(try!(File::open(filename)).read_to_end(&mut proto));
  try!(session.extend_graph(&proto));

  // Load the test data into the session.
  let mut init_step = Step::new();
  try!(init_step.add_input("x", &x));
  try!(init_step.add_input("y", &y));
  try!(init_step.add_target("init"));
  try!(session.run(&mut init_step));

  // Train the model.
  let mut train_step = Step::new();
  try!(train_step.add_input("x", &x));
  try!(train_step.add_input("y", &y));
  try!(train_step.add_target("train"));
  for _ in 0..steps {
    try!(session.run(&mut train_step));
  }

  // Grab the data out of the session.
  let mut output_step = Step::new();
  let w_ix = try!(output_step.request_output("w"));
  let b_ix = try!(output_step.request_output("b"));
  try!(session.run(&mut output_step));

  // Check our results.
  let w_hat: f32 = try!(output_step.take_output(w_ix)).data()[0];
  let b_hat: f32 = try!(output_step.take_output(b_ix)).data()[0];
  println!("Checking w: expected {}, got {}. {}", w, w_hat,
           if (w - w_hat).abs() < 1e-3 {"Success!"} else {"FAIL"});
  println!("Checking b: expected {}, got {}. {}", b, b_hat,
           if (b - b_hat).abs() < 1e-3 {"Success!"} else {"FAIL"});
  Ok(())
}
<commit_msg>Fix path in examples/regression.rs<commit_after>// -*-  indent-tabs-mode:nil; tab-width:2;  -*-
extern crate random;
extern crate tensorflow;

use random::Source;
use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::result::Result;
use std::path::Path;
use std::process::exit;
use tensorflow::Code;
use tensorflow::Session;
use tensorflow::SessionOptions;
use tensorflow::Status;
use tensorflow::Step;
use tensorflow::Tensor;

fn main() {
  // Putting the main code in another function serves two purposes:
  // 1. We can use the try! macro.
  // 2. We can call exit safely, which does not run any destructors.
  exit(match run() {
    Ok(_) => 0,
    Err(e) => {
      println!("{}", e);
      1
    }
  })
}

fn run() -> Result<(), Box<Error>> {
  let filename = "examples/regression-model/model.pb"; // y = w * x + b
  if !Path::new(filename).exists() {
    return Err(Box::new(Status::new_set(Code::NotFound, &format!(
      "Run 'python regression.py' to generate {} and try again.", filename)).unwrap()));
  }

  // Generate some test data.
  let w = 0.1;
  let b = 0.3;
  let num_points = 100;
  let steps = 201;
  let mut rand = random::default();
  let mut x = Tensor::new(&[num_points as u64]);
  let mut y = Tensor::new(&[num_points as u64]);
  for i in 0..num_points {
    x[i] = (2.0 * rand.read::<f64>() - 1.0) as f32;
    y[i] = w * x[i] + b;
  }

  // Load the computation graph defined by regression.py.
  let mut session = try!(Session::new(&SessionOptions::new()));
  let mut proto = Vec::new();
  try!(try!(File::open(filename)).read_to_end(&mut proto));
  try!(session.extend_graph(&proto));

  // Load the test data into the session.
  let mut init_step = Step::new();
  try!(init_step.add_input("x", &x));
  try!(init_step.add_input("y", &y));
  try!(init_step.add_target("init"));
  try!(session.run(&mut init_step));

  // Train the model.
  let mut train_step = Step::new();
  try!(train_step.add_input("x", &x));
  try!(train_step.add_input("y", &y));
  try!(train_step.add_target("train"));
  for _ in 0..steps {
    try!(session.run(&mut train_step));
  }

  // Grab the data out of the session.
  let mut output_step = Step::new();
  let w_ix = try!(output_step.request_output("w"));
  let b_ix = try!(output_step.request_output("b"));
  try!(session.run(&mut output_step));

  // Check our results.
  let w_hat: f32 = try!(output_step.take_output(w_ix)).data()[0];
  let b_hat: f32 = try!(output_step.take_output(b_ix)).data()[0];
  println!("Checking w: expected {}, got {}. {}", w, w_hat,
           if (w - w_hat).abs() < 1e-3 {"Success!"} else {"FAIL"});
  println!("Checking b: expected {}, got {}. {}", b, b_hat,
           if (b - b_hat).abs() < 1e-3 {"Success!"} else {"FAIL"});
  Ok(())
}
<|endoftext|>