<commit_before>use reexport::*;
use rustc::hir;
use rustc::hir::*;
use rustc::hir::intravisit::{FnKind, Visitor, walk_ty, NestedVisitorMap};
use rustc::lint::*;
use rustc::ty::{self, Ty};
use std::cmp::Ordering;
use syntax::ast::{IntTy, UintTy, FloatTy};
use syntax::attr::IntType;
use syntax::codemap::Span;
use utils::{comparisons, higher, in_external_macro, in_macro, match_def_path, snippet, span_help_and_lint, span_lint,
            opt_def_id, last_path_segment, type_size};
use utils::paths;

/// Handles all the linting of funky types
#[allow(missing_copy_implementations)]
pub struct TypePass;

/// **What it does:** Checks for use of `Box<Vec<_>>` anywhere in the code.
///
/// **Why is this bad?** `Vec` already keeps its contents in a separate area on
/// the heap. So if you `Box` it, you just add another level of indirection
/// without any benefit whatsoever.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// struct X {
///     values: Box<Vec<Foo>>,
/// }
/// ```
declare_lint! {
    pub BOX_VEC,
    Warn,
    "usage of `Box<Vec<T>>`, vector elements are already on the heap"
}

/// **What it does:** Checks for usage of any `LinkedList`, suggesting to use a
/// `Vec` or a `VecDeque` (formerly called `RingBuf`).
///
/// **Why is this bad?** Gankro says:
///
/// > The TL;DR of `LinkedList` is that it's built on a massive amount of pointers and indirection.
/// > It wastes memory, it has terrible cache locality, and is all-around slow. `RingBuf`, while
/// > "only" amortized for push/pop, should be faster in the general case for almost every possible
/// > workload, and isn't even amortized at all if you can predict the capacity you need.
/// >
/// > `LinkedList`s are only really good if you're doing a lot of merging or splitting of lists.
/// > This is because they can just mangle some pointers instead of actually copying the data. Even
/// > if you're doing a lot of insertion in the middle of the list, `RingBuf` can still be better
/// > because of how expensive it is to seek to the middle of a `LinkedList`.
///
/// **Known problems:** False positives – the instances where using a
/// `LinkedList` makes sense are few and far between, but they can still happen.
///
/// **Example:**
/// ```rust
/// let x = LinkedList::new();
/// ```
declare_lint! {
    pub LINKEDLIST,
    Warn,
    "usage of LinkedList, usually a vector is faster, or a more specialized data \
     structure like a VecDeque"
}

/// **What it does:** Checks for use of `&Box<T>` anywhere in the code.
///
/// **Why is this bad?** Any `&Box<T>` can also be a `&T`, which is more general.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// fn foo(bar: &Box<T>) { ... }
/// ```
declare_lint! {
    pub BORROWED_BOX,
    Warn,
    "a borrow of a boxed type"
}

impl LintPass for TypePass {
    fn get_lints(&self) -> LintArray {
        lint_array!(BOX_VEC, LINKEDLIST, BORROWED_BOX)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass {
    fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Body, _: Span, id: NodeId) {
        // skip trait implementations, see #605
        if let Some(map::NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent(id)) {
            if let ItemImpl(_, _, _, _, Some(..), _, _) = item.node {
                return;
            }
        }

        check_fn_decl(cx, decl);
    }

    fn check_struct_field(&mut self, cx: &LateContext, field: &StructField) {
        check_ty(cx, &field.ty);
    }

    fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
        match item.node {
            TraitItemKind::Const(ref ty, _) |
            TraitItemKind::Type(_, Some(ref ty)) => check_ty(cx, ty),
            TraitItemKind::Method(ref sig, _) => check_fn_decl(cx, &sig.decl),
            _ => (),
        }
    }
}

fn check_fn_decl(cx: &LateContext, decl: &FnDecl) {
    for input in &decl.inputs {
        check_ty(cx, input);
    }

    if let FunctionRetTy::Return(ref ty) = decl.output {
        check_ty(cx, ty);
    }
}

fn check_ty(cx: &LateContext, ast_ty: &hir::Ty) {
    if in_macro(ast_ty.span) {
        return;
    }
    match ast_ty.node {
        TyPath(ref qpath) => {
            let def = cx.tables.qpath_def(qpath, ast_ty.id);
            if let Some(def_id) = opt_def_id(def) {
                if Some(def_id) == cx.tcx.lang_items.owned_box() {
                    let last = last_path_segment(qpath);
                    if_let_chain! {[
                        let PathParameters::AngleBracketedParameters(ref ag) = last.parameters,
                        let Some(vec) = ag.types.get(0),
                        let TyPath(ref qpath) = vec.node,
                        let def::Def::Struct(..) = cx.tables.qpath_def(qpath, vec.id),
                        let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, vec.id)),
                        match_def_path(cx.tcx, did, &paths::VEC),
                    ], {
                        span_help_and_lint(cx,
                                           BOX_VEC,
                                           ast_ty.span,
                                           "you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`",
                                           "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation.");
                        return; // don't recurse into the type
                    }}
                } else if match_def_path(cx.tcx, def_id, &paths::LINKED_LIST) {
                    span_help_and_lint(cx,
                                       LINKEDLIST,
                                       ast_ty.span,
                                       "I see you're using a LinkedList! Perhaps you meant some other data structure?",
                                       "a VecDeque might work");
                    return; // don't recurse into the type
                }
            }
            match *qpath {
                QPath::Resolved(Some(ref ty), ref p) => {
                    check_ty(cx, ty);
                    for ty in p.segments.iter().flat_map(|seg| seg.parameters.types()) {
                        check_ty(cx, ty);
                    }
                },
                QPath::Resolved(None, ref p) => {<commit_msg>Fix typo in types check<commit_after>use reexport::*;
use rustc::hir;
use rustc::hir::*;
use rustc::hir::intravisit::{FnKind, Visitor, walk_ty, NestedVisitorMap};
use rustc::lint::*;
use rustc::ty::{self, Ty};
use std::cmp::Ordering;
use syntax::ast::{IntTy, UintTy, FloatTy};
use syntax::attr::IntType;
use syntax::codemap::Span;
use utils::{comparisons, higher, in_external_macro, in_macro, match_def_path, snippet, span_help_and_lint, span_lint,
            opt_def_id, last_path_segment, type_size};
use utils::paths;

/// Handles all the linting of funky types
#[allow(missing_copy_implementations)]
pub struct TypePass;

/// **What it does:** Checks for use of `Box<Vec<_>>` anywhere in the code.
///
/// **Why is this bad?** `Vec` already keeps its contents in a separate area on
/// the heap. So if you `Box` it, you just add another level of indirection
/// without any benefit whatsoever.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// struct X {
///     values: Box<Vec<Foo>>,
/// }
/// ```
declare_lint! {
    pub BOX_VEC,
    Warn,
    "usage of `Box<Vec<T>>`, vector elements are already on the heap"
}

/// **What it does:** Checks for usage of any `LinkedList`, suggesting to use a
/// `Vec` or a `VecDeque` (formerly called `RingBuf`).
///
/// **Why is this bad?** Gankro says:
///
/// > The TL;DR of `LinkedList` is that it's built on a massive amount of pointers and indirection.
/// > It wastes memory, it has terrible cache locality, and is all-around slow. `RingBuf`, while
/// > "only" amortized for push/pop, should be faster in the general case for almost every possible
/// > workload, and isn't even amortized at all if you can predict the capacity you need.
/// >
/// > `LinkedList`s are only really good if you're doing a lot of merging or splitting of lists.
/// > This is because they can just mangle some pointers instead of actually copying the data. Even
/// > if you're doing a lot of insertion in the middle of the list, `RingBuf` can still be better
/// > because of how expensive it is to seek to the middle of a `LinkedList`.
///
/// **Known problems:** False positives – the instances where using a
/// `LinkedList` makes sense are few and far between, but they can still happen.
///
/// **Example:**
/// ```rust
/// let x = LinkedList::new();
/// ```
declare_lint! {
    pub LINKEDLIST,
    Warn,
    "usage of LinkedList, usually a vector is faster, or a more specialized data \
     structure like a VecDeque"
}

/// **What it does:** Checks for use of `&Box<T>` anywhere in the code.
///
/// **Why is this bad?** Any `&Box<T>` can also be a `&T`, which is more general.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// fn foo(bar: &Box<T>) { ... }
/// ```
declare_lint! {
    pub BORROWED_BOX,
    Warn,
    "a borrow of a boxed type"
}

impl LintPass for TypePass {
    fn get_lints(&self) -> LintArray {
        lint_array!(BOX_VEC, LINKEDLIST, BORROWED_BOX)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass {
    fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Body, _: Span, id: NodeId) {
        // skip trait implementations, see #605
        if let Some(map::NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent(id)) {
            if let ItemImpl(_, _, _, _, Some(..), _, _) = item.node {
                return;
            }
        }

        check_fn_decl(cx, decl);
    }

    fn check_struct_field(&mut self, cx: &LateContext, field: &StructField) {
        check_ty(cx, &field.ty);
    }

    fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
        match item.node {
            TraitItemKind::Const(ref ty, _) |
            TraitItemKind::Type(_, Some(ref ty)) => check_ty(cx, ty),
            TraitItemKind::Method(ref sig, _) => check_fn_decl(cx, &sig.decl),
            _ => (),
        }
    }
}

fn check_fn_decl(cx: &LateContext, decl: &FnDecl) {
    for input in &decl.inputs {
        check_ty(cx, input);
    }

    if let FunctionRetTy::Return(ref ty) = decl.output {
        check_ty(cx, ty);
    }
}

fn check_ty(cx: &LateContext, ast_ty: &hir::Ty) {
    if in_macro(ast_ty.span) {
        return;
    }
    match ast_ty.node {
        TyPath(ref qpath) => {
            let def = cx.tables.qpath_def(qpath, ast_ty.id);
            if let Some(def_id) = opt_def_id(def) {
                if Some(def_id) == cx.tcx.lang_items.owned_box() {
                    let last = last_path_segment(qpath);
                    if_let_chain! {[
                        let PathParameters::AngleBracketedParameters(ref ag) = last.parameters,
                        let Some(vec) = ag.types.get(0),
                        let TyPath(ref qpath) = vec.node,
                        let def::Def::Struct(..) = cx.tables.qpath_def(qpath, vec.id),
                        let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, vec.id)),
                        match_def_path(cx.tcx, did, &paths::VEC),
                    ], {
                        span_help_and_lint(cx,
                                           BORROWED_BOX,
                                           ast_ty.span,
                                           "you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`",
                                           "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation.");
                        return; // don't recurse into the type
                    }}
                } else if match_def_path(cx.tcx, def_id, &paths::LINKED_LIST) {
                    span_help_and_lint(cx,
                                       LINKEDLIST,
                                       ast_ty.span,
                                       "I see you're using a LinkedList! Perhaps you meant some other data structure?",
                                       "a VecDeque might work");
                    return; // don't recurse into the type
                }
            }
            match *qpath {
                QPath::Resolved(Some(ref ty), ref p) => {
                    check_ty(cx, ty);
                    for ty in p.segments.iter().flat_map(|seg| seg.parameters.types()) {
                        check_ty(cx, ty);
                    }
                },
                QPath::Resolved(None, ref p) => {
{'fraction_non_alphanumeric': 0.1383627862746652, 'fraction_numerical': 0.0006339646564704018, 'mean_word_length': 1.958968347010551, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 28, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4118343', 'n_tokens_mistral': 3955, 'n_tokens_neox': 3828, 'n_words': 1172}