<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of `make clean` in rustbuild.
//!
//! Responsible for cleaning out a build directory of all old and stale
//! artifacts to prepare for a fresh build. Currently doesn't remove the
//! `build/cache` directory (download cache) or the `build/$target/llvm`
//! directory as we want that cached between builds.

use std::fs;
use std::path::Path;

use build::Build;

pub fn clean(build: &Build) {
    for host in build.config.host.iter() {

        let out = build.out.join(host);

        rm_rf(build, &out.join("compiler-rt"));
        rm_rf(build, &out.join("doc"));

        for stage in 0..4 {
            rm_rf(build, &out.join(format!("stage{}", stage)));
            rm_rf(build, &out.join(format!("stage{}-std", stage)));
            rm_rf(build, &out.join(format!("stage{}-rustc", stage)));
            rm_rf(build, &out.join(format!("stage{}-tools", stage)));
            rm_rf(build, &out.join(format!("stage{}-test", stage)));
        }
    }
}

fn rm_rf(build: &Build, path: &Path) {
    if path.exists() {
        build.verbose(&format!("removing `{}`", path.display()));
        t!(fs::remove_dir_all(path));
    }
}
<commit_msg>Auto merge of #34577 - alexcrichton:clean-more-yet-again, r=brson<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of `make clean` in rustbuild.
//!
//! Responsible for cleaning out a build directory of all old and stale
//! artifacts to prepare for a fresh build. Currently doesn't remove the
//! `build/cache` directory (download cache) or the `build/$target/llvm`
//! directory as we want that cached between builds.

use std::fs;
use std::path::Path;

use build::Build;

pub fn clean(build: &Build) {
    rm_rf(build, "tmp".as_ref());
    rm_rf(build, &build.out.join("tmp"));

    for host in build.config.host.iter() {

        let out = build.out.join(host);

        rm_rf(build, &out.join("compiler-rt"));
        rm_rf(build, &out.join("doc"));

        for stage in 0..4 {
            rm_rf(build, &out.join(format!("stage{}", stage)));
            rm_rf(build, &out.join(format!("stage{}-std", stage)));
            rm_rf(build, &out.join(format!("stage{}-rustc", stage)));
            rm_rf(build, &out.join(format!("stage{}-tools", stage)));
            rm_rf(build, &out.join(format!("stage{}-test", stage)));
        }
    }
}

fn rm_rf(build: &Build, path: &Path) {
    if path.exists() {
        build.verbose(&format!("removing `{}`", path.display()));
        t!(fs::remove_dir_all(path));
    }
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use rustc::ty;
use rustc::hir::*;
use syntax::codemap::Span;
use utils::{match_def_path, paths, span_note_and_lint};

/// **What it does:** Checks for calls to `std::mem::drop` with a reference
/// instead of an owned value.
///
/// **Why is this bad?** Calling `drop` on a reference will only drop the
/// reference itself, which is a no-op. It will not call the `drop` method (from
/// the `Drop` trait implementation) on the underlying referenced value, which
/// is likely what was intended.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let mut lock_guard = mutex.lock();
/// std::mem::drop(&lock_guard) // Should have been drop(lock_guard), mutex still locked
/// operation_that_requires_mutex_to_be_unlocked();
/// ```
declare_lint! {
    pub DROP_REF,
    Warn,
    "calls to `std::mem::drop` with a reference instead of an owned value"
}

#[allow(missing_copy_implementations)]
pub struct Pass;

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

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if let ExprCall(ref path, ref args) = expr.node {
            if let ExprPath(ref qpath) = path.node {
                let def_id = cx.tcx.tables().qpath_def(qpath, path.id).def_id();
                if match_def_path(cx, def_id, &paths::DROP) {
                    if args.len() != 1 {
                        return;
                    }
                    check_drop_arg(cx, expr.span, &args[0]);
                }
            }
        }
    }
}

fn check_drop_arg(cx: &LateContext, call_span: Span, arg: &Expr) {
    let arg_ty = cx.tcx.tables().expr_ty(arg);
    if let ty::TyRef(..) = arg_ty.sty {
        span_note_and_lint(cx,
                           DROP_REF,
                           call_span,
                           "call to `std::mem::drop` with a reference argument. \
                           Dropping a reference does nothing",
                           arg.span,
                           &format!("argument has type {}", arg_ty.sty));
    }
}
<commit_msg>Refactor drop_ref.rs to use the if_let_chain macro.<commit_after>use rustc::lint::*;
use rustc::ty;
use rustc::hir::*;
use utils::{match_def_path, paths, span_note_and_lint};

/// **What it does:** Checks for calls to `std::mem::drop` with a reference
/// instead of an owned value.
///
/// **Why is this bad?** Calling `drop` on a reference will only drop the
/// reference itself, which is a no-op. It will not call the `drop` method (from
/// the `Drop` trait implementation) on the underlying referenced value, which
/// is likely what was intended.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let mut lock_guard = mutex.lock();
/// std::mem::drop(&lock_guard) // Should have been drop(lock_guard), mutex still locked
/// operation_that_requires_mutex_to_be_unlocked();
/// ```
declare_lint! {
    pub DROP_REF,
    Warn,
    "calls to `std::mem::drop` with a reference instead of an owned value"
}

#[allow(missing_copy_implementations)]
pub struct Pass;

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

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if_let_chain!{[
            let ExprCall(ref path, ref args) = expr.node,
            let ExprPath(ref qpath) = path.node,
            match_def_path(cx, cx.tcx.tables().qpath_def(qpath, path.id).def_id(), &paths::DROP),
            args.len() == 1,
        ], {
            let arg = &args[0];
            let arg_ty = cx.tcx.tables().expr_ty(arg);
            if let ty::TyRef(..) = arg_ty.sty {
                span_note_and_lint(cx,
                                   DROP_REF,
                                   expr.span,
                                   "call to `std::mem::drop` with a reference argument. \
                                   Dropping a reference does nothing",
                                   arg.span,
                                   &format!("argument has type {}", arg_ty.sty));
            }
        }}
    }
}
<|endoftext|>


<commit_before>use crate::utils::{
    get_item_name, in_macro_or_desugar, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty,
};
use rustc::hir::def_id::DefId;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::ty;
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use syntax::ast::{LitKind, Name};
use syntax::source_map::{Span, Spanned};

declare_clippy_lint! {
    /// **What it does:** Checks for getting the length of something via `.len()`
    /// just to compare to zero, and suggests using `.is_empty()` where applicable.
    ///
    /// **Why is this bad?** Some structures can answer `.is_empty()` much faster
    /// than calculating their length. Notably, for slices, getting the length
    /// requires a subtraction whereas `.is_empty()` is just a comparison. So it is
    /// good to get into the habit of using `.is_empty()`, and having it is cheap.
    /// Besides, it makes the intent clearer than a manual comparison.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```ignore
    /// if x.len() == 0 {
    ///     ..
    /// }
    /// if y.len() != 0 {
    ///     ..
    /// }
    /// ```
    /// instead use
    /// ```ignore
    /// if x.is_empty() {
    ///     ..
    /// }
    /// if !y.is_empty() {
    ///     ..
    /// }
    /// ```
    pub LEN_ZERO,
    style,
    "checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead"
}

declare_clippy_lint! {
    /// **What it does:** Checks for items that implement `.len()` but not
    /// `.is_empty()`.
    ///
    /// **Why is this bad?** It is good custom to have both methods, because for
    /// some data structures, asking about the length will be a costly operation,
    /// whereas `.is_empty()` can usually answer in constant time. Also it used to
    /// lead to false positives on the [`len_zero`](#len_zero) lint – currently that
    /// lint will ignore such entities.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```ignore
    /// impl X {
    ///     pub fn len(&self) -> usize {
    ///         ..
    ///     }
    /// }
    /// ```
    pub LEN_WITHOUT_IS_EMPTY,
    style,
    "traits or impls with a public `len` method but no corresponding `is_empty` method"
}

declare_lint_pass!(LenZero => [LEN_ZERO, LEN_WITHOUT_IS_EMPTY]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
        if in_macro_or_desugar(item.span) {
            return;
        }

        match item.node {
            ItemKind::Trait(_, _, _, _, ref trait_items) => check_trait_items(cx, item, trait_items),
            ItemKind::Impl(_, _, _, _, None, _, ref impl_items) => check_impl_items(cx, item, impl_items),
            _ => (),
        }
    }

    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if in_macro_or_desugar(expr.span) {
            return;
        }

        if let ExprKind::Binary(Spanned { node: cmp, .. }, ref left, ref right) = expr.node {
            match cmp {
                BinOpKind::Eq => {
                    check_cmp(cx, expr.span, left, right, "", 0); // len == 0
                    check_cmp(cx, expr.span, right, left, "", 0); // 0 == len
                },
                BinOpKind::Ne => {
                    check_cmp(cx, expr.span, left, right, "!", 0); // len != 0
                    check_cmp(cx, expr.span, right, left, "!", 0); // 0 != len
                },
                BinOpKind::Gt => {
                    check_cmp(cx, expr.span, left, right, "!", 0); // len > 0
                    check_cmp(cx, expr.span, right, left, "", 1); // 1 > len
                },
                BinOpKind::Lt => {
                    check_cmp(cx, expr.span, left, right, "", 1); // len < 1
                    check_cmp(cx, expr.span, right, left, "!", 0); // 0 < len
                },
                BinOpKind::Ge => check_cmp(cx, expr.span, left, right, "!", 1), // len >= 1
                BinOpKind::Le => check_cmp(cx, expr.span, right, left, "!", 1), // 1 <= len
                _ => (),
            }
        }
    }
}

fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items: &[TraitItemRef]) {
    fn is_named_self(cx: &LateContext<'_, '_>, item: &TraitItemRef, name: &str) -> bool {
        item.ident.name.as_str() == name
            && if let AssocItemKind::Method { has_self } = item.kind {
                has_self && {
                    let did = cx.tcx.hir().local_def_id(item.id.hir_id);
                    cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1
                }
            } else {
                false
            }
    }

    // fill the set with current and super traits
    fn fill_trait_set(traitt: DefId, set: &mut FxHashSet<DefId>, cx: &LateContext<'_, '_>) {
        if set.insert(traitt) {
            for supertrait in rustc::traits::supertrait_def_ids(cx.tcx, traitt) {
                fill_trait_set(supertrait, set, cx);
            }
        }
    }

    if cx.access_levels.is_exported(visited_trait.hir_id) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) {
        let mut current_and_super_traits = FxHashSet::default();
        let visited_trait_def_id = cx.tcx.hir().local_def_id(visited_trait.hir_id);
        fill_trait_set(visited_trait_def_id, &mut current_and_super_traits, cx);

        let is_empty_method_found = current_and_super_traits
            .iter()
            .flat_map(|&i| cx.tcx.associated_items(i))
            .any(|i| {
                i.kind == ty::AssocKind::Method
                    && i.method_has_self_argument
                    && i.ident.name == sym!(is_empty)
                    && cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1
            });

        if !is_empty_method_found {
            span_lint(
                cx,
                LEN_WITHOUT_IS_EMPTY,
                visited_trait.span,
                &format!(
                    "trait `{}` has a `len` method but no (possibly inherited) `is_empty` method",
                    visited_trait.ident.name
                ),
            );
        }
    }
}

fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplItemRef]) {
    fn is_named_self(cx: &LateContext<'_, '_>, item: &ImplItemRef, name: &str) -> bool {
        item.ident.name.as_str() == name
            && if let AssocItemKind::Method { has_self } = item.kind {
                has_self && {
                    let did = cx.tcx.hir().local_def_id(item.id.hir_id);
                    cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1
                }
            } else {
                false
            }
    }

    let is_empty = if let Some(is_empty) = impl_items.iter().find(|i| is_named_self(cx, i, "is_empty")) {
        if cx.access_levels.is_exported(is_empty.id.hir_id) {
            return;
        } else {
            "a private"
        }
    } else {
        "no corresponding"
    };

    if let Some(i) = impl_items.iter().find(|i| is_named_self(cx, i, "len")) {
        if cx.access_levels.is_exported(i.id.hir_id) {
            let def_id = cx.tcx.hir().local_def_id(item.hir_id);
            let ty = cx.tcx.type_of(def_id);

            span_lint(
                cx,
                LEN_WITHOUT_IS_EMPTY,
                item.span,
                &format!(
                    "item `{}` has a public `len` method but {} `is_empty` method",
                    ty, is_empty
                ),
            );
        }
    }
}

fn check_cmp(cx: &LateContext<'_, '_>, span: Span, method: &Expr, lit: &Expr, op: &str, compare_to: u32) {
    if let (&ExprKind::MethodCall(ref method_path, _, ref args), &ExprKind::Lit(ref lit)) = (&method.node, &lit.node) {
        // check if we are in an is_empty() method
        if let Some(name) = get_item_name(cx, method) {
            if name.as_str() == "is_empty" {
                return;
            }
        }

        check_len(cx, span, method_path.ident.name, args, &lit.node, op, compare_to)
    }
}

fn check_len(
    cx: &LateContext<'_, '_>,
    span: Span,
    method_name: Name,
    args: &[Expr],
    lit: &LitKind,
    op: &str,
    compare_to: u32,
) {
    if let LitKind::Int(lit, _) = *lit {
        // check if length is compared to the specified number
        if lit != u128::from(compare_to) {
            return;
        }

        if method_name.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) {
            let mut applicability = Applicability::MachineApplicable;
            span_lint_and_sugg(
                cx,
                LEN_ZERO,
                span,
                &format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }),
                "using `is_empty` is clearer and more explicit",
                format!(
                    "{}{}.is_empty()",
                    op,
                    snippet_with_applicability(cx, args[0].span, "_", &mut applicability)
                ),
                applicability,
            );
        }
    }
}

/// Checks if this type has an `is_empty` method.
fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
    /// Gets an `AssocItem` and return true if it matches `is_empty(self)`.
    fn is_is_empty(cx: &LateContext<'_, '_>, item: &ty::AssocItem) -> bool {
        if let ty::AssocKind::Method = item.kind {
            if item.ident.name.as_str() == "is_empty" {
                let sig = cx.tcx.fn_sig(item.def_id);
                let ty = sig.skip_binder();
                ty.inputs().len() == 1
            } else {
                false
            }
        } else {
            false
        }
    }

    /// Checks the inherent impl's items for an `is_empty(self)` method.
    fn has_is_empty_impl(cx: &LateContext<'_, '_>, id: DefId) -> bool {
        cx.tcx
            .inherent_impls(id)
            .iter()
            .any(|imp| cx.tcx.associated_items(*imp).any(|item| is_is_empty(cx, &item)))
    }

    let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr));
    match ty.sty {
        ty::Dynamic(ref tt, ..) => {
            if let Some(principal) = tt.principal() {
                cx.tcx
                    .associated_items(principal.def_id())
                    .any(|item| is_is_empty(cx, &item))
            } else {
                false
            }
        },
        ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id),
        ty::Adt(id, _) => has_is_empty_impl(cx, id.did),
        ty::Array(..) | ty::Slice(..) | ty::Str => true,
        _ => false,
    }
}
<commit_msg>Add required negation in non_zero lint<commit_after>use crate::utils::{
    get_item_name, in_macro_or_desugar, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty,
};
use rustc::hir::def_id::DefId;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::ty;
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use syntax::ast::{LitKind, Name};
use syntax::source_map::{Span, Spanned};

declare_clippy_lint! {
    /// **What it does:** Checks for getting the length of something via `.len()`
    /// just to compare to zero, and suggests using `.is_empty()` where applicable.
    ///
    /// **Why is this bad?** Some structures can answer `.is_empty()` much faster
    /// than calculating their length. Notably, for slices, getting the length
    /// requires a subtraction whereas `.is_empty()` is just a comparison. So it is
    /// good to get into the habit of using `.is_empty()`, and having it is cheap.
    /// Besides, it makes the intent clearer than a manual comparison.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```ignore
    /// if x.len() == 0 {
    ///     ..
    /// }
    /// if y.len() != 0 {
    ///     ..
    /// }
    /// ```
    /// instead use
    /// ```ignore
    /// if x.is_empty() {
    ///     ..
    /// }
    /// if !y.is_empty() {
    ///     ..
    /// }
    /// ```
    pub LEN_ZERO,
    style,
    "checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead"
}

declare_clippy_lint! {
    /// **What it does:** Checks for items that implement `.len()` but not
    /// `.is_empty()`.
    ///
    /// **Why is this bad?** It is good custom to have both methods, because for
    /// some data structures, asking about the length will be a costly operation,
    /// whereas `.is_empty()` can usually answer in constant time. Also it used to
    /// lead to false positives on the [`len_zero`](#len_zero) lint – currently that
    /// lint will ignore such entities.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```ignore
    /// impl X {
    ///     pub fn len(&self) -> usize {
    ///         ..
    ///     }
    /// }
    /// ```
    pub LEN_WITHOUT_IS_EMPTY,
    style,
    "traits or impls with a public `len` method but no corresponding `is_empty` method"
}

declare_lint_pass!(LenZero => [LEN_ZERO, LEN_WITHOUT_IS_EMPTY]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
        if in_macro_or_desugar(item.span) {
            return;
        }

        match item.node {
            ItemKind::Trait(_, _, _, _, ref trait_items) => check_trait_items(cx, item, trait_items),
            ItemKind::Impl(_, _, _, _, None, _, ref impl_items) => check_impl_items(cx, item, impl_items),
            _ => (),
        }
    }

    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if in_macro_or_desugar(expr.span) {
            return;
        }

        if let ExprKind::Binary(Spanned { node: cmp, .. }, ref left, ref right) = expr.node {
            match cmp {
                BinOpKind::Eq => {
                    check_cmp(cx, expr.span, left, right, "", 0); // len == 0
                    check_cmp(cx, expr.span, right, left, "", 0); // 0 == len
                },
                BinOpKind::Ne => {
                    check_cmp(cx, expr.span, left, right, "!", 0); // len != 0
                    check_cmp(cx, expr.span, right, left, "!", 0); // 0 != len
                },
                BinOpKind::Gt => {
                    check_cmp(cx, expr.span, left, right, "!", 0); // len > 0
                    check_cmp(cx, expr.span, right, left, "", 1); // 1 > len
                },
                BinOpKind::Lt => {
                    check_cmp(cx, expr.span, left, right, "", 1); // len < 1
                    check_cmp(cx, expr.span, right, left, "!", 0); // 0 < len
                },
                BinOpKind::Ge => check_cmp(cx, expr.span, left, right, "!", 1), // len >= 1
                BinOpKind::Le => check_cmp(cx, expr.span, right, left, "!", 1), // 1 <= len
                _ => (),
            }
        }
    }
}

fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items: &[TraitItemRef]) {
    fn is_named_self(cx: &LateContext<'_, '_>, item: &TraitItemRef, name: &str) -> bool {
        item.ident.name.as_str() == name
            && if let AssocItemKind::Method { has_self } = item.kind {
                has_self && {
                    let did = cx.tcx.hir().local_def_id(item.id.hir_id);
                    cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1
                }
            } else {
                false
            }
    }

    // fill the set with current and super traits
    fn fill_trait_set(traitt: DefId, set: &mut FxHashSet<DefId>, cx: &LateContext<'_, '_>) {
        if set.insert(traitt) {
            for supertrait in rustc::traits::supertrait_def_ids(cx.tcx, traitt) {
                fill_trait_set(supertrait, set, cx);
            }
        }
    }

    if cx.access_levels.is_exported(visited_trait.hir_id) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) {
        let mut current_and_super_traits = FxHashSet::default();
        let visited_trait_def_id = cx.tcx.hir().local_def_id(visited_trait.hir_id);
        fill_trait_set(visited_trait_def_id, &mut current_and_super_traits, cx);

        let is_empty_method_found = current_and_super_traits
            .iter()
            .flat_map(|&i| cx.tcx.associated_items(i))
            .any(|i| {
                i.kind == ty::AssocKind::Method
                    && i.method_has_self_argument
                    && i.ident.name == sym!(is_empty)
                    && cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1
            });

        if !is_empty_method_found {
            span_lint(
                cx,
                LEN_WITHOUT_IS_EMPTY,
                visited_trait.span,
                &format!(
                    "trait `{}` has a `len` method but no (possibly inherited) `is_empty` method",
                    visited_trait.ident.name
                ),
            );
        }
    }
}

fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplItemRef]) {
    fn is_named_self(cx: &LateContext<'_, '_>, item: &ImplItemRef, name: &str) -> bool {
        item.ident.name.as_str() == name
            && if let AssocItemKind::Method { has_self } = item.kind {
                has_self && {
                    let did = cx.tcx.hir().local_def_id(item.id.hir_id);
                    cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1
                }
            } else {
                false
            }
    }

    let is_empty = if let Some(is_empty) = impl_items.iter().find(|i| is_named_self(cx, i, "is_empty")) {
        if cx.access_levels.is_exported(is_empty.id.hir_id) {
            return;
        } else {
            "a private"
        }
    } else {
        "no corresponding"
    };

    if let Some(i) = impl_items.iter().find(|i| is_named_self(cx, i, "len")) {
        if cx.access_levels.is_exported(i.id.hir_id) {
            let def_id = cx.tcx.hir().local_def_id(item.hir_id);
            let ty = cx.tcx.type_of(def_id);

            span_lint(
                cx,
                LEN_WITHOUT_IS_EMPTY,
                item.span,
                &format!(
                    "item `{}` has a public `len` method but {} `is_empty` method",
                    ty, is_empty
                ),
            );
        }
    }
}

fn check_cmp(cx: &LateContext<'_, '_>, span: Span, method: &Expr, lit: &Expr, op: &str, compare_to: u32) {
    if let (&ExprKind::MethodCall(ref method_path, _, ref args), &ExprKind::Lit(ref lit)) = (&method.node, &lit.node) {
        // check if we are in an is_empty() method
        if let Some(name) = get_item_name(cx, method) {
            if name.as_str() == "is_empty" {
                return;
            }
        }

        check_len(cx, span, method_path.ident.name, args, &lit.node, op, compare_to)
    }
}

fn check_len(
    cx: &LateContext<'_, '_>,
    span: Span,
    method_name: Name,
    args: &[Expr],
    lit: &LitKind,
    op: &str,
    compare_to: u32,
) {
    if let LitKind::Int(lit, _) = *lit {
        // check if length is compared to the specified number
        if lit != u128::from(compare_to) {
            return;
        }

        if method_name.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) {
            let mut applicability = Applicability::MachineApplicable;
            span_lint_and_sugg(
                cx,
                LEN_ZERO,
                span,
                &format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }),
                &format!("using `{}is_empty` is clearer and more explicit", op),
                format!(
                    "{}{}.is_empty()",
                    op,
                    snippet_with_applicability(cx, args[0].span, "_", &mut applicability)
                ),
                applicability,
            );
        }
    }
}

/// Checks if this type has an `is_empty` method.
fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
    /// Gets an `AssocItem` and return true if it matches `is_empty(self)`.
    fn is_is_empty(cx: &LateContext<'_, '_>, item: &ty::AssocItem) -> bool {
        if let ty::AssocKind::Method = item.kind {
            if item.ident.name.as_str() == "is_empty" {
                let sig = cx.tcx.fn_sig(item.def_id);
                let ty = sig.skip_binder();
                ty.inputs().len() == 1
            } else {
                false
            }
        } else {
            false
        }
    }

    /// Checks the inherent impl's items for an `is_empty(self)` method.
    fn has_is_empty_impl(cx: &LateContext<'_, '_>, id: DefId) -> bool {
        cx.tcx
            .inherent_impls(id)
            .iter()
            .any(|imp| cx.tcx.associated_items(*imp).any(|item| is_is_empty(cx, &item)))
    }

    let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr));
    match ty.sty {
        ty::Dynamic(ref tt, ..) => {
            if let Some(principal) = tt.principal() {
                cx.tcx
                    .associated_items(principal.def_id())
                    .any(|item| is_is_empty(cx, &item))
            } else {
                false
            }
        },
        ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id),
        ty::Adt(id, _) => has_is_empty_impl(cx, id.did),
        ty::Array(..) | ty::Slice(..) | ty::Str => true,
        _ => false,
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate modparse_derive;
#[macro_use]
extern crate derive_builder;
#[macro_use]
extern crate torchrs;
#[macro_use]
extern crate clap;

use torchrs::autograd::{Variable, VariableArgs, VarAccess};
use torchrs::optim;
use torchrs::optim::OptimVal;
use torchrs::nn;
use torchrs::nn::{InitModuleStruct, GetFieldStruct, ModIntf, ModDelegate, Module};
use torchrs::nn::functional as F;
use torchrs::utils::data as D;
use torchrs::utils::torchvision::{datasets, transforms};
use torchrs::tensor;

use clap::{Arg, App};
#[derive(Clone, Builder)]
struct NetArgs {
    #[builder(default="64")]
    batch_size: usize,
    #[builder(default="1000")]
    test_batch_size: usize,
    #[builder(default="10")]
    epochs: u32,
    #[builder(default="0.01")]
    lr: f32,
    #[builder(default="0.5")]
    momentum: f32,
    #[builder(default="true")]
    cuda: bool,
    #[builder(default="1")]
    seed: usize,
    #[builder(default="10")]
    log_interval: usize,
}

impl Default for NetArgs {
    fn default() -> Self {
        NetArgsBuilder::default().build().unwrap()
    }
}

fn parse_args() -> NetArgs {
    let mut args = NetArgs::default();
    let matches = App::new("Torch.rs MNIST Example")
        .version("0.1")
        .author("Some Guy")
        .about("recognize handwritten digits")
        .arg(Arg::with_name("batch-size").takes_value(true))
        .arg(Arg::with_name("test-batch-size").takes_value(true))
        .arg(Arg::with_name("epochs").takes_value(true))
        .arg(Arg::with_name("lr").takes_value(true))
        .arg(Arg::with_name("momentum").takes_value(true))
        .arg(Arg::with_name("no-cuda").takes_value(false))
        .arg(Arg::with_name("seed").takes_value(true))
        .arg(Arg::with_name("log-interval").takes_value(true))
        .get_matches();
    let (b_size, tb_size, epochs, lr, momentum, seed, log_int) =
        (value_t!(matches.value_of("batch-size"), usize).ok(),
         value_t!(matches.value_of("test-batch-size"), usize).ok(),
         value_t!(matches.value_of("epochs"), u32).ok(),
         value_t!(matches.value_of("lr"), f32).ok(),
         value_t!(matches.value_of("momentum"), f32).ok(),
         value_t!(matches.value_of("seed"), usize).ok(),
         value_t!(matches.value_of("log-interval"), usize).ok());
    if let Some(b_size) = b_size {
        args.batch_size = b_size
    }
    if let Some(tb_size) = tb_size {
        args.test_batch_size = tb_size
    }
    if let Some(epochs) = epochs {
        args.epochs = epochs
    }
    if let Some(lr) = lr {
        args.lr = lr
    }
    if let Some(momentum) = momentum {
        args.momentum = momentum
    }
    if let Some(seed) = seed {
        args.seed = seed
    }
    if let Some(log_int) = log_int {
        args.log_interval = log_int
    }
    //XXX CUDA?
    args
}

#[derive(ModParse)]
struct Net<T: tensor::NumLimits> {
    delegate: nn::Module<T>,
    conv1: nn::Conv2d<T>,
    conv2: nn::Conv2d<T>,
    fc1: nn::Linear<T>,
    fc2: nn::Linear<T>,
}

impl<T: tensor::NumLimits> Net<T> {
    pub fn new() -> Net<T> {
        Net {
                delegate: nn::Module::new(),
                conv1: nn::Conv2d::build(1, 10, (5, 5)).done(),
                conv2: nn::Conv2d::build(10, 20, (5, 5)).done(),
                fc1: nn::Linear::build(320, 50).done(),
                fc2: nn::Linear::build(50, 10).done(),
            }
            .init_module()
    }
}
impl_mod_delegate!(Net);

// The forward operations could take on one of two implementations.
// The first supporting a near verbatim version of the python
// implementation, and the second supporting a slightly more
// idiomatic to Rust method chaining.

// a) as a near verbatim implementation of the python version
impl<T: tensor::NumLimits> ModIntf<T> for Net<T> {
    fn forward(&mut self, args: &mut Variable<T>) -> Variable<T> {
        let pool_val = F::MaxPool2dArgs::default();
        let mut dropout_val = F::DropoutArgs::default();
        dropout_val.training = self.delegate.training;
        let mut x = F::relu(F::max_pool2d(self.conv1.f(args.clone()), (2, 2), &pool_val));
        x = F::relu(F::max_pool2d(F::dropout2d(self.conv2.f(x), &dropout_val),
                                  (2, 2),
                                  &pool_val));
        x = x.view([-1, 320]);
        x = F::relu(self.fc1.f(x));
        x = F::dropout(x, &dropout_val);
        x = self.fc2.f(x);
        F::log_softmax(x)
    }
}

fn train(model: &mut Net<f32>,
         args: &NetArgs,
         train_loader: &D::BatchLoader<f32, i64>,
         epoch: u32,
         optimizer: &mut optim::OptIntf<f32>) {
    model.train();
    for (batch_idx, (ref data, ref target)) in train_loader.iter().enumerate() {
        let (mut data, target) = if args.cuda {
            (Variable::new(data.cuda(None).clone()), Variable::new(target.cuda(None).clone()))
        } else {
            (Variable::new(data.clone()), Variable::new(target.clone()))
        };
        optimizer.zero_grad(model);
        let output = model.f(data.clone());
        let mut loss = F::nll_loss(output, target, &F::NLLLossArgs::default());
        loss.backward();
        optimizer.step(model);
        model.free_graph();
        if batch_idx % args.log_interval == 0 {
            println!("Train Epoch: {} [{}/{} ({:.0}%)]\tLoss: {:.6}",
                     epoch,
                     batch_idx * data.data().len(),
                     train_loader.dataset.len(),
                     100. * (batch_idx as f32) / train_loader.len() as f32,
                     loss.data()[0]);
        }
    }
}

fn test(model: &mut Net<f32>, args: &NetArgs, test_loader: &D::BatchLoader<f32, i64>) {
    model.eval();
    let mut test_loss = 0.;
    let mut correct = 0;
    for (ref data, ref target) in test_loader.iter() {
        let varargs = VariableArgs {
            volatile: true,
            ..Default::default()
        };
        let (data, mut target) = if args.cuda {
            (Variable::new_args(data.cuda(None).clone(), &varargs),
             Variable::new(target.cuda(None).clone()))
        } else {
            (Variable::new_args(data.clone(), &varargs), Variable::new(target.clone()))
        };
        let mut output = model.f(data);
        test_loss += F::nll_loss(output.clone(), target.clone(), &F::NLLLossArgs::default());
        let pred = output.data().max_reduce(1).1;
        correct += pred.eq_tensor(&*target.data()).cpu().sum() as u32;
    }
    test_loss /= test_loader.len() as f32;
    println!("\nTest set: Average loss: {:.4}, Accuracy: {}/{} ({:.0}%)\n",
             test_loss,
             correct,
             test_loader.dataset.len(),
             100. * (correct as f32) / (test_loader.dataset.len() as f32))

}

fn main() {
    let train_loader: D::BatchLoader<f32, i64> =
        D::DataLoader::new(datasets::MNIST::<f32>::build("../data")
                               .download(true)
                               .done(None),
                           D::DataLoaderArgs::default());

    let test_loader: D::BatchLoader<f32, i64> =
        D::DataLoader::new(datasets::MNIST::<f32>::build("../data")
                               .train(false)
                               .done(None),
                           D::DataLoaderArgs::default());
    let args = parse_args();
    let mut model = Net::new();
    let mut optimizer = optim::SGD::new(map_opt!{"lr" => args.lr, "momentum" => args.momentum});
    for epoch in 1..args.epochs + 1 {
        train(&mut model, &args, &train_loader, epoch, &mut optimizer);
        test(&mut model, &args, &test_loader);
    }
}
<commit_msg>pass batch size to dataset<commit_after>#[macro_use]
extern crate modparse_derive;
#[macro_use]
extern crate derive_builder;
#[macro_use]
extern crate torchrs;
#[macro_use]
extern crate clap;

use torchrs::autograd::{Variable, VariableArgs, VarAccess};
use torchrs::optim;
use torchrs::optim::OptimVal;
use torchrs::nn;
use torchrs::nn::{InitModuleStruct, GetFieldStruct, ModIntf, ModDelegate, Module};
use torchrs::nn::functional as F;
use torchrs::utils::data as D;
use torchrs::utils::torchvision::{datasets, transforms};
use torchrs::tensor;

use clap::{Arg, App};
#[derive(Clone, Builder)]
struct NetArgs {
    #[builder(default="64")]
    batch_size: usize,
    #[builder(default="1000")]
    test_batch_size: usize,
    #[builder(default="10")]
    epochs: u32,
    #[builder(default="0.01")]
    lr: f32,
    #[builder(default="0.5")]
    momentum: f32,
    #[builder(default="true")]
    cuda: bool,
    #[builder(default="1")]
    seed: usize,
    #[builder(default="10")]
    log_interval: usize,
}

impl Default for NetArgs {
    fn default() -> Self {
        NetArgsBuilder::default().build().unwrap()
    }
}

fn parse_args() -> NetArgs {
    let mut args = NetArgs::default();
    let matches = App::new("Torch.rs MNIST Example")
        .version("0.1")
        .author("Some Guy")
        .about("recognize handwritten digits")
        .arg(Arg::with_name("batch-size").takes_value(true))
        .arg(Arg::with_name("test-batch-size").takes_value(true))
        .arg(Arg::with_name("epochs").takes_value(true))
        .arg(Arg::with_name("lr").takes_value(true))
        .arg(Arg::with_name("momentum").takes_value(true))
        .arg(Arg::with_name("no-cuda").takes_value(false))
        .arg(Arg::with_name("seed").takes_value(true))
        .arg(Arg::with_name("log-interval").takes_value(true))
        .get_matches();
    let (b_size, tb_size, epochs, lr, momentum, seed, log_int) =
        (value_t!(matches.value_of("batch-size"), usize).ok(),
         value_t!(matches.value_of("test-batch-size"), usize).ok(),
         value_t!(matches.value_of("epochs"), u32).ok(),
         value_t!(matches.value_of("lr"), f32).ok(),
         value_t!(matches.value_of("momentum"), f32).ok(),
         value_t!(matches.value_of("seed"), usize).ok(),
         value_t!(matches.value_of("log-interval"), usize).ok());
    if let Some(b_size) = b_size {
        args.batch_size = b_size
    }
    if let Some(tb_size) = tb_size {
        args.test_batch_size = tb_size
    }
    if let Some(epochs) = epochs {
        args.epochs = epochs
    }
    if let Some(lr) = lr {
        args.lr = lr
    }
    if let Some(momentum) = momentum {
        args.momentum = momentum
    }
    if let Some(seed) = seed {
        args.seed = seed
    }
    if let Some(log_int) = log_int {
        args.log_interval = log_int
    }
    //XXX CUDA?
    args
}

#[derive(ModParse)]
struct Net<T: tensor::NumLimits> {
    delegate: nn::Module<T>,
    conv1: nn::Conv2d<T>,
    conv2: nn::Conv2d<T>,
    fc1: nn::Linear<T>,
    fc2: nn::Linear<T>,
}

impl<T: tensor::NumLimits> Net<T> {
    pub fn new() -> Net<T> {
        Net {
                delegate: nn::Module::new(),
                conv1: nn::Conv2d::build(1, 10, (5, 5)).done(),
                conv2: nn::Conv2d::build(10, 20, (5, 5)).done(),
                fc1: nn::Linear::build(320, 50).done(),
                fc2: nn::Linear::build(50, 10).done(),
            }
            .init_module()
    }
}
impl_mod_delegate!(Net);

// The forward operations could take on one of two implementations.
// The first supporting a near verbatim version of the python
// implementation, and the second supporting a slightly more
// idiomatic to Rust method chaining.

// a) as a near verbatim implementation of the python version
impl<T: tensor::NumLimits> ModIntf<T> for Net<T> {
    fn forward(&mut self, args: &mut Variable<T>) -> Variable<T> {
        let pool_val = F::MaxPool2dArgs::default();
        let mut dropout_val = F::DropoutArgs::default();
        dropout_val.training = self.delegate.training;
        let mut x = F::relu(F::max_pool2d(self.conv1.f(args.clone()), (2, 2), &pool_val));
        x = F::relu(F::max_pool2d(F::dropout2d(self.conv2.f(x), &dropout_val),
                                  (2, 2),
                                  &pool_val));
        x = x.view([-1, 320]);
        x = F::relu(self.fc1.f(x));
        x = F::dropout(x, &dropout_val);
        x = self.fc2.f(x);
        F::log_softmax(x)
    }
}

fn train(model: &mut Net<f32>,
         args: &NetArgs,
         train_loader: &D::BatchLoader<f32, i64>,
         epoch: u32,
         optimizer: &mut optim::OptIntf<f32>) {
    model.train();
    for (batch_idx, (ref data, ref target)) in train_loader.iter().enumerate() {
        let (mut data, target) = if args.cuda {
            (Variable::new(data.cuda(None).clone()), Variable::new(target.cuda(None).clone()))
        } else {
            (Variable::new(data.clone()), Variable::new(target.clone()))
        };
        optimizer.zero_grad(model);
        let output = model.f(data.clone());
        let mut loss = F::nll_loss(output, target, &F::NLLLossArgs::default());
        loss.backward();
        optimizer.step(model);
        model.free_graph();
        if batch_idx % args.log_interval == 0 {
            println!("Train Epoch: {} [{}/{} ({:.0}%)]\tLoss: {:.6}",
                     epoch,
                     batch_idx * data.data().len(),
                     train_loader.dataset.len(),
                     100. * (batch_idx as f32) / train_loader.len() as f32,
                     loss.data()[0]);
        }
    }
}

fn test(model: &mut Net<f32>, args: &NetArgs, test_loader: &D::BatchLoader<f32, i64>) {
    model.eval();
    let mut test_loss = 0.;
    let mut correct = 0;
    for (ref data, ref target) in test_loader.iter() {
        let varargs = VariableArgs {
            volatile: true,
            ..Default::default()
        };
        let (data, mut target) = if args.cuda {
            (Variable::new_args(data.cuda(None).clone(), &varargs),
             Variable::new(target.cuda(None).clone()))
        } else {
            (Variable::new_args(data.clone(), &varargs), Variable::new(target.clone()))
        };
        let mut output = model.f(data);
        test_loss += F::nll_loss(output.clone(), target.clone(), &F::NLLLossArgs::default());
        let pred = output.data().max_reduce(1).1;
        correct += pred.eq_tensor(&*target.data()).cpu().sum() as u32;
    }
    test_loss /= test_loader.len() as f32;
    println!("\nTest set: Average loss: {:.4}, Accuracy: {}/{} ({:.0}%)\n",
             test_loss,
             correct,
             test_loader.dataset.len(),
             100. * (correct as f32) / (test_loader.dataset.len() as f32))

}

fn main() {
    let args = parse_args();
    let train_loader: D::BatchLoader<f32, i64> = D::DataLoader::build()
        .batch_size(args.batch_size)
        .done(datasets::MNIST::<f32>::build("../data")
                  .download(false)
                  .done(None));

    let test_loader: D::BatchLoader<f32, i64> = D::DataLoader::build()
        .batch_size(args.batch_size)
        .done(datasets::MNIST::<f32>::build("../data")
                  .train(false)
                  .done(None));
    let mut model = Net::new();
    let mut optimizer = optim::SGD::new(map_opt!{"lr" => args.lr, "momentum" => args.momentum});
    for epoch in 1..args.epochs + 1 {
        train(&mut model, &args, &train_loader, epoch, &mut optimizer);
        test(&mut model, &args, &test_loader);
    }
}
<|endoftext|>


<commit_before>use std;
use glfw3;
import to_str::ToStr;
import glfw3::*;

fn main() {
    if (glfwInit() == 0) {
        fail(~"glfwInit() failed\n");
    }

    let dt_mode = glfwGetDesktopMode();
    io::println(~"Desktop mode:\n" + mode_str(dt_mode));

    let modes = glfwGetVideoModes();

    io::println(~"Available modes:");
    modes.map(|m| { io::println(mode_str(m)) });

    glfwTerminate();
}

fn mode_str(mode: GLFWvidmode) -> ~str {
    fmt!("%d x %d\t%d (%d %d %d)",
          mode.width as int, mode.height as int,
          (mode.redBits + mode.blueBits + mode.greenBits) as int,
          mode.redBits as int, mode.blueBits as int, mode.greenBits as int)
}<commit_msg>Remove unused import<commit_after>use std;
use glfw3;
import glfw3::*;

fn main() {
    if (glfwInit() == 0) {
        fail(~"glfwInit() failed\n");
    }

    let dt_mode = glfwGetDesktopMode();
    io::println(~"Desktop mode:\n" + mode_str(dt_mode));

    let modes = glfwGetVideoModes();

    io::println(~"Available modes:");
    modes.map(|m| { io::println(mode_str(m)) });

    glfwTerminate();
}

fn mode_str(mode: GLFWvidmode) -> ~str {
    fmt!("%d x %d\t%d (%d %d %d)",
         mode.width as int, mode.height as int,
         (mode.redBits + mode.blueBits + mode.greenBits) as int,
         mode.redBits as int, mode.blueBits as int, mode.greenBits as int)
}<|endoftext|>


<commit_before>#[macro_use]
extern crate frunk;
// for derives
extern crate frunk_core;
// for labelledgeneric
extern crate frunk_proc_macros;

use frunk_core::path::PathTraverser;
use frunk_proc_macros::{path, Path};

#[derive(LabelledGeneric)]
struct Dog<'a> {
    name: &'a str,
    dimensions: Dimensions,
}

#[derive(LabelledGeneric)]
struct Cat<'a> {
    name: &'a str,
    dimensions: Dimensions,
}

#[derive(LabelledGeneric)]
struct Dimensions {
    height: usize,
    width: usize,
    unit: SizeUnit,
}

#[derive(Debug)]
enum SizeUnit {
    Cm,
    Inch,
}

fn main() {
let dog = Dog {
    name: "Joe",
    dimensions: Dimensions {
        height: 10,
        width: 5,
        unit: SizeUnit::Inch,
    },
};

let cat = Cat {
    name: "Schmoe",
    dimensions: Dimensions {
        height: 7,
        width: 3,
        unit: SizeUnit::Cm,
    },
};

// Prints height as long as `A` has the right "shape" (e.g.
// has `dimensions.height: usize` and `dimension.unit: SizeUnit)
fn print_height<'a, A, HeightIdx, UnitIdx>(obj: &'a A) -> ()
where
    &'a A: PathTraverser<Path!(dimensions.height), HeightIdx, TargetValue = &'a usize>
        + PathTraverser<Path!(dimensions.unit), UnitIdx, TargetValue = &'a SizeUnit>,
{
    println!(
        "Height [{} {:?}]",
        path!(dimensions.height).get(obj),
        path!(dimensions.unit).get(obj)
    );
}

print_height(&dog);
print_height(&cat);
}
<commit_msg>* Fix examples alignment<commit_after>#[macro_use]
extern crate frunk;
// for derives
extern crate frunk_core;
// for labelledgeneric
extern crate frunk_proc_macros;

use frunk_core::path::PathTraverser;
use frunk_proc_macros::{path, Path};

#[derive(LabelledGeneric)]
struct Dog<'a> {
    name: &'a str,
    dimensions: Dimensions,
}

#[derive(LabelledGeneric)]
struct Cat<'a> {
    name: &'a str,
    dimensions: Dimensions,
}

#[derive(LabelledGeneric)]
struct Dimensions {
    height: usize,
    width: usize,
    unit: SizeUnit,
}

#[derive(Debug)]
enum SizeUnit {
    Cm,
    Inch,
}

fn main() {
    let dog = Dog {
        name: "Joe",
        dimensions: Dimensions {
            height: 10,
            width: 5,
            unit: SizeUnit::Inch,
        },
    };

    let cat = Cat {
        name: "Schmoe",
        dimensions: Dimensions {
            height: 7,
            width: 3,
            unit: SizeUnit::Cm,
        },
    };

    // Prints height as long as `A` has the right "shape" (e.g.
    // has `dimensions.height: usize` and `dimension.unit: SizeUnit)
    fn print_height<'a, A, HeightIdx, UnitIdx>(obj: &'a A) -> ()
    where
        &'a A: PathTraverser<Path!(dimensions.height), HeightIdx, TargetValue = &'a usize>
            + PathTraverser<Path!(dimensions.unit), UnitIdx, TargetValue = &'a SizeUnit>,
    {
        println!(
            "Height [{} {:?}]",
            path!(dimensions.height).get(obj),
            path!(dimensions.unit).get(obj)
        );
    }

    print_height(&dog);
    print_height(&cat);
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fs;
use std::path::Path;

use crate::core::compiler::unit_dependencies;
use crate::core::compiler::UnitInterner;
use crate::core::compiler::{
    BuildConfig, BuildContext, CompileKind, CompileMode, Context, ProfileKind,
};
use crate::core::profiles::UnitFor;
use crate::core::Workspace;
use crate::ops;
use crate::util::errors::{CargoResult, CargoResultExt};
use crate::util::paths;
use crate::util::Config;

pub struct CleanOptions<'a> {
    pub config: &'a Config,
    /// A list of packages to clean. If empty, everything is cleaned.
    pub spec: Vec<String>,
    /// The target arch triple to clean, or None for the host arch
    pub target: Option<String>,
    /// Whether to clean the release directory
    pub profile_specified: bool,
    /// Whether to clean the directory of a certain build profile
    pub profile_kind: ProfileKind,
    /// Whether to just clean the doc directory
    pub doc: bool,
}

/// Cleans the package's build artifacts.
pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
    let mut target_dir = ws.target_dir();
    let config = ws.config();

    // If the doc option is set, we just want to delete the doc directory.
    if opts.doc {
        target_dir = target_dir.join("doc");
        return rm_rf(&target_dir.into_path_unlocked(), config);
    }

    let (packages, resolve) = ops::resolve_ws(ws)?;
    let profiles = ws.profiles();

    // Check for whether the profile is defined.
    let _ = profiles.base_profile(&opts.profile_kind)?;

    if opts.profile_specified {
        // After parsing profiles we know the dir-name of the profile, if a profile
        // was passed from the command line. If so, delete only the directory of
        // that profile.
        let dir_name = profiles.get_dir_name(&opts.profile_kind);
        target_dir = target_dir.join(dir_name);
    }

    // If we have a spec, then we need to delete some packages, otherwise, just
    // remove the whole target directory and be done with it!
    //
    // Note that we don't bother grabbing a lock here as we're just going to
    // blow it all away anyway.
    if opts.spec.is_empty() {
        return rm_rf(&target_dir.into_path_unlocked(), config);
    }

    let interner = UnitInterner::new();
    let mut build_config = BuildConfig::new(config, Some(1), &opts.target, CompileMode::Build)?;
    let profile_kind = opts.profile_kind.clone();
    build_config.profile_kind = profile_kind.clone();
    let bcx = BuildContext::new(
        ws,
        &packages,
        opts.config,
        &build_config,
        profiles,
        &interner,
        HashMap::new(),
    )?;
    let mut units = Vec::new();

    for spec in opts.spec.iter() {
        // Translate the spec to a Package
        let pkgid = resolve.query(spec)?;
        let pkg = packages.get_one(pkgid)?;

        // Generate all relevant `Unit` targets for this package
        for target in pkg.targets() {
            for kind in [CompileKind::Host, build_config.requested_kind].iter() {
                for mode in CompileMode::all_modes() {
                    for unit_for in UnitFor::all_values() {
                        let profile = if mode.is_run_custom_build() {
                            profiles.get_profile_run_custom_build(&profiles.get_profile(
                                pkg.package_id(),
                                ws.is_member(pkg),
                                *unit_for,
                                CompileMode::Build,
                                profile_kind.clone(),
                            ))
                        } else {
                            profiles.get_profile(
                                pkg.package_id(),
                                ws.is_member(pkg),
                                *unit_for,
                                *mode,
                                profile_kind.clone(),
                            )
                        };
                        let features = resolve.features_sorted(pkg.package_id());
                        units.push(bcx.units.intern(
                            pkg, target, profile, *kind, *mode, features, /*is_std*/ false,
                        ));
                    }
                }
            }
        }
    }

    let unit_dependencies =
        unit_dependencies::build_unit_dependencies(&bcx, &resolve, None, &units, &[])?;
    let mut cx = Context::new(config, &bcx, unit_dependencies, build_config.requested_kind)?;
    cx.prepare_units(None, &units)?;

    for unit in units.iter() {
        if unit.mode.is_doc() || unit.mode.is_doc_test() {
            // Cleaning individual rustdoc crates is currently not supported.
            // For example, the search index would need to be rebuilt to fully
            // remove it (otherwise you're left with lots of broken links).
            // Doc tests produce no output.
            continue;
        }
        rm_rf(&cx.files().fingerprint_dir(unit), config)?;
        if unit.target.is_custom_build() {
            if unit.mode.is_run_custom_build() {
                rm_rf(&cx.files().build_script_out_dir(unit), config)?;
            } else {
                rm_rf(&cx.files().build_script_dir(unit), config)?;
            }
            continue;
        }

        for output in cx.outputs(unit)?.iter() {
            rm_rf(&output.path, config)?;
            if let Some(ref dst) = output.hardlink {
                rm_rf(dst, config)?;
            }
        }
    }

    Ok(())
}

fn rm_rf(path: &Path, config: &Config) -> CargoResult<()> {
    let m = fs::metadata(path);
    if m.as_ref().map(|s| s.is_dir()).unwrap_or(false) {
        config
            .shell()
            .verbose(|shell| shell.status("Removing", path.display()))?;
        paths::remove_dir_all(path)
            .chain_err(|| failure::format_err!("could not remove build directory"))?;
    } else if m.is_ok() {
        config
            .shell()
            .verbose(|shell| shell.status("Removing", path.display()))?;
        paths::remove_file(path)
            .chain_err(|| failure::format_err!("failed to remove build artifact"))?;
    }
    Ok(())
}
<commit_msg>Auto merge of #7502 - matthiaskrgr:dont_lock_target_dir_7490, r=ehuss<commit_after>use std::collections::HashMap;
use std::fs;
use std::path::Path;

use crate::core::compiler::unit_dependencies;
use crate::core::compiler::UnitInterner;
use crate::core::compiler::{
    BuildConfig, BuildContext, CompileKind, CompileMode, Context, ProfileKind,
};
use crate::core::profiles::UnitFor;
use crate::core::Workspace;
use crate::ops;
use crate::util::errors::{CargoResult, CargoResultExt};
use crate::util::paths;
use crate::util::Config;

pub struct CleanOptions<'a> {
    pub config: &'a Config,
    /// A list of packages to clean. If empty, everything is cleaned.
    pub spec: Vec<String>,
    /// The target arch triple to clean, or None for the host arch
    pub target: Option<String>,
    /// Whether to clean the release directory
    pub profile_specified: bool,
    /// Whether to clean the directory of a certain build profile
    pub profile_kind: ProfileKind,
    /// Whether to just clean the doc directory
    pub doc: bool,
}

/// Cleans the package's build artifacts.
pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
    let mut target_dir = ws.target_dir();
    let config = ws.config();

    // If the doc option is set, we just want to delete the doc directory.
    if opts.doc {
        target_dir = target_dir.join("doc");
        return rm_rf(&target_dir.into_path_unlocked(), config);
    }

    let profiles = ws.profiles();

    // Check for whether the profile is defined.
    let _ = profiles.base_profile(&opts.profile_kind)?;

    if opts.profile_specified {
        // After parsing profiles we know the dir-name of the profile, if a profile
        // was passed from the command line. If so, delete only the directory of
        // that profile.
        let dir_name = profiles.get_dir_name(&opts.profile_kind);
        target_dir = target_dir.join(dir_name);
    }

    // If we have a spec, then we need to delete some packages, otherwise, just
    // remove the whole target directory and be done with it!
    //
    // Note that we don't bother grabbing a lock here as we're just going to
    // blow it all away anyway.
    if opts.spec.is_empty() {
        return rm_rf(&target_dir.into_path_unlocked(), config);
    }
    let (packages, resolve) = ops::resolve_ws(ws)?;

    let interner = UnitInterner::new();
    let mut build_config = BuildConfig::new(config, Some(1), &opts.target, CompileMode::Build)?;
    let profile_kind = opts.profile_kind.clone();
    build_config.profile_kind = profile_kind.clone();
    let bcx = BuildContext::new(
        ws,
        &packages,
        opts.config,
        &build_config,
        profiles,
        &interner,
        HashMap::new(),
    )?;
    let mut units = Vec::new();

    for spec in opts.spec.iter() {
        // Translate the spec to a Package
        let pkgid = resolve.query(spec)?;
        let pkg = packages.get_one(pkgid)?;

        // Generate all relevant `Unit` targets for this package
        for target in pkg.targets() {
            for kind in [CompileKind::Host, build_config.requested_kind].iter() {
                for mode in CompileMode::all_modes() {
                    for unit_for in UnitFor::all_values() {
                        let profile = if mode.is_run_custom_build() {
                            profiles.get_profile_run_custom_build(&profiles.get_profile(
                                pkg.package_id(),
                                ws.is_member(pkg),
                                *unit_for,
                                CompileMode::Build,
                                profile_kind.clone(),
                            ))
                        } else {
                            profiles.get_profile(
                                pkg.package_id(),
                                ws.is_member(pkg),
                                *unit_for,
                                *mode,
                                profile_kind.clone(),
                            )
                        };
                        let features = resolve.features_sorted(pkg.package_id());
                        units.push(bcx.units.intern(
                            pkg, target, profile, *kind, *mode, features, /*is_std*/ false,
                        ));
                    }
                }
            }
        }
    }

    let unit_dependencies =
        unit_dependencies::build_unit_dependencies(&bcx, &resolve, None, &units, &[])?;
    let mut cx = Context::new(config, &bcx, unit_dependencies, build_config.requested_kind)?;
    cx.prepare_units(None, &units)?;

    for unit in units.iter() {
        if unit.mode.is_doc() || unit.mode.is_doc_test() {
            // Cleaning individual rustdoc crates is currently not supported.
            // For example, the search index would need to be rebuilt to fully
            // remove it (otherwise you're left with lots of broken links).
            // Doc tests produce no output.
            continue;
        }
        rm_rf(&cx.files().fingerprint_dir(unit), config)?;
        if unit.target.is_custom_build() {
            if unit.mode.is_run_custom_build() {
                rm_rf(&cx.files().build_script_out_dir(unit), config)?;
            } else {
                rm_rf(&cx.files().build_script_dir(unit), config)?;
            }
            continue;
        }

        for output in cx.outputs(unit)?.iter() {
            rm_rf(&output.path, config)?;
            if let Some(ref dst) = output.hardlink {
                rm_rf(dst, config)?;
            }
        }
    }

    Ok(())
}

fn rm_rf(path: &Path, config: &Config) -> CargoResult<()> {
    let m = fs::metadata(path);
    if m.as_ref().map(|s| s.is_dir()).unwrap_or(false) {
        config
            .shell()
            .verbose(|shell| shell.status("Removing", path.display()))?;
        paths::remove_dir_all(path)
            .chain_err(|| failure::format_err!("could not remove build directory"))?;
    } else if m.is_ok() {
        config
            .shell()
            .verbose(|shell| shell.status("Removing", path.display()))?;
        paths::remove_file(path)
            .chain_err(|| failure::format_err!("failed to remove build artifact"))?;
    }
    Ok(())
}
<|endoftext|>


<commit_before>//! This is the Buffer module for Xtensis.

// This file is part of Xtensis.

// This is the Xtensis text editor; it edits text.
// Copyright (C) 2016-2017  The Xtensis Developers

// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see
// <http://www.gnu.org/licenses/>.

extern crate slog;

use logging::init_logger;
use server::gapbuffer::GapBuffer;
use std::path::PathBuf;
use utils::types::BufferID;
use utils::uuid::get_uuid_buffer;

/// Struct for a Buffer in Xtensis
/// This stores metadata about a buffer.
#[derive(Debug)]
pub struct Buffer {
    /// UUID of a buffer.
    pub buffer_uuid: BufferID,
    /// File path of a buffer.
    pub file_path: Option<PathBuf>,
    /// Active status of a buffer.
    pub active: bool,
    /// Temporary status of a buffer.
    pub temporary: bool,
    /// If a buffer is r/o.
    /// If this is `true`, then r/w is `false.`
    /// Likewise, if this is `false`, then r/w is `true.
    pub read_only: bool,
    /// Major mode of a buffer
    pub major_mode: &'static str,
    /// Vector of Minor modes in a buffer
    pub minor_modes: Vec<&'static str>,
    /// Dirty status of a buffer
    pub dirty: bool,
    /// Contents of a buffer.
    pub text: GapBuffer<u8>,
}

impl Buffer {
    /// Return a new instance of `Buffer`.
    pub fn new() -> Buffer {
        let buffer_uuid = get_uuid_buffer();

        let logger = init_logger().new(o!("buffer_uuid" =>
                                          buffer_uuid.clone()));
        Buffer {
            buffer_uuid: buffer_uuid,
            file_path: None,
            active: false,
            temporary: false,
            read_only: false,
            major_mode: "fundamental-mode",
            minor_modes: Vec::new(),
            dirty: false,
            text: GapBuffer::new(),
        }
    }

    /// Return true if a buffer is active.
    /// That is to say, a 'focused' buffer, or otherwise in-use, and
    /// *not* inactive.
    /// If it's not a active buffer, then return false.
    pub fn is_active(&self) -> bool {
        self.active
    }

    /// Return true if a buffer is temporary.
    /// If it's not a temporary buffer, then return false.
    /// A temporary buffer is defined by the characteristic of having
    /// no 'target' to save to.
    pub fn is_temporary(&self) -> bool {
        self.temporary
    }

    /// Return true if a buffer is read only.

    /// If it's not read-only, then it returns false, and the buffer
    /// will be presumed to be read-write.

    /// A read-only buffer is defined by the characteristic of the FS
    /// denying write access, or being set manually.
    pub fn is_ro(&self) -> bool {
        self.read_only
    }

    /// Return true if a buffer is dirty.
    /// If it's not dirty, then return false.
    /// A dirty buffer is defined by the characteristic of the buffer
    /// having changed since the last save.
    /// Temporary buffers are *exempt* from this field.
    pub fn is_dirty(&self) -> bool {
        self.dirty
    }

    /// Return the current major mode of a buffer.
    pub fn get_major_mode(&self) -> &str {
        self.major_mode
    }

    /// Return a `Vec<&'static str>` of minor modes.
    pub fn get_minor_modes(&self) -> Vec<&'static str> {
        self.minor_modes.clone()
    }

    /// Return the length of a buffer.
    pub fn get_buffer_length(&self) -> usize {
        self.text.len()
    }
}

impl Default for Buffer {
    fn default() -> Buffer {
        Buffer::new()
    }
}

#[cfg(test)]
mod test {
    use super::Buffer;

    #[test]
    fn test_buffer_default_values() {
        let buf = Buffer::new();

        assert_eq!(None, buf.file_path);
        assert_eq!(false, buf.active);
        assert_eq!(false, buf.is_active());

        assert_eq!(false, buf.temporary);
        assert_eq!(false, buf.is_temporary());

        assert_eq!(false, buf.read_only);
        assert_eq!(false, buf.is_ro());

        assert_eq!("fundamental-mode", buf.major_mode);
        assert_eq!(false, buf.dirty);
    }

    #[test]
    fn test_buffer_major_minor_modes() {
        let mut buf = Buffer::new();
        buf.major_mode = "rust-mode";
        buf.minor_modes.push("auto-wrap-mode");
        buf.minor_modes.push("spell-check-mode");
        buf.minor_modes.push("complete-me-mode");
        buf.minor_modes.push("language-server-mode");

        assert_eq!(4, buf.minor_modes.len());
        assert_eq!("rust-mode", buf.major_mode);
    }
}
<commit_msg>Add missing logger field<commit_after>//! This is the Buffer module for Xtensis.

// This file is part of Xtensis.

// This is the Xtensis text editor; it edits text.
// Copyright (C) 2016-2017  The Xtensis Developers

// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see
// <http://www.gnu.org/licenses/>.

extern crate slog;

use logging::init_logger;
use server::gapbuffer::GapBuffer;
use std::path::PathBuf;
use utils::types::BufferID;
use utils::uuid::get_uuid_buffer;

/// Struct for a Buffer in Xtensis
/// This stores metadata about a buffer.
#[derive(Debug)]
pub struct Buffer {
    /// UUID of a buffer.
    pub buffer_uuid: BufferID,
    /// File path of a buffer.
    pub file_path: Option<PathBuf>,
    /// Active status of a buffer.
    pub active: bool,
    /// Temporary status of a buffer.
    pub temporary: bool,
    /// If a buffer is r/o.
    /// If this is `true`, then r/w is `false.`
    /// Likewise, if this is `false`, then r/w is `true.
    pub read_only: bool,
    /// Major mode of a buffer
    pub major_mode: &'static str,
    /// Vector of Minor modes in a buffer
    pub minor_modes: Vec<&'static str>,
    /// Dirty status of a buffer
    pub dirty: bool,
    /// Contents of a buffer.
    pub text: GapBuffer<u8>,
    /// Logger instance.
    pub logger: slog::Logger,
}

impl Buffer {
    /// Return a new instance of `Buffer`.
    pub fn new() -> Buffer {
        let buffer_uuid = get_uuid_buffer();

        let logger = init_logger().new(o!("buffer_uuid" =>
                                          buffer_uuid.clone()));
        Buffer {
            buffer_uuid: buffer_uuid,
            file_path: None,
            active: false,
            temporary: false,
            read_only: false,
            major_mode: "fundamental-mode",
            minor_modes: Vec::new(),
            dirty: false,
            text: GapBuffer::new(),
            logger: logger,
        }
    }

    /// Return true if a buffer is active.
    /// That is to say, a 'focused' buffer, or otherwise in-use, and
    /// *not* inactive.
    /// If it's not a active buffer, then return false.
    pub fn is_active(&self) -> bool {
        self.active
    }

    /// Return true if a buffer is temporary.
    /// If it's not a temporary buffer, then return false.
    /// A temporary buffer is defined by the characteristic of having
    /// no 'target' to save to.
    pub fn is_temporary(&self) -> bool {
        self.temporary
    }

    /// Return true if a buffer is read only.

    /// If it's not read-only, then it returns false, and the buffer
    /// will be presumed to be read-write.

    /// A read-only buffer is defined by the characteristic of the FS
    /// denying write access, or being set manually.
    pub fn is_ro(&self) -> bool {
        self.read_only
    }

    /// Return true if a buffer is dirty.
    /// If it's not dirty, then return false.
    /// A dirty buffer is defined by the characteristic of the buffer
    /// having changed since the last save.
    /// Temporary buffers are *exempt* from this field.
    pub fn is_dirty(&self) -> bool {
        self.dirty
    }

    /// Return the current major mode of a buffer.
    pub fn get_major_mode(&self) -> &str {
        self.major_mode
    }

    /// Return a `Vec<&'static str>` of minor modes.
    pub fn get_minor_modes(&self) -> Vec<&'static str> {
        self.minor_modes.clone()
    }

    /// Return the length of a buffer.
    pub fn get_buffer_length(&self) -> usize {
        self.text.len()
    }
}

impl Default for Buffer {
    fn default() -> Buffer {
        Buffer::new()
    }
}

#[cfg(test)]
mod test {
    use super::Buffer;

    #[test]
    fn test_buffer_default_values() {
        let buf = Buffer::new();

        assert_eq!(None, buf.file_path);
        assert_eq!(false, buf.active);
        assert_eq!(false, buf.is_active());

        assert_eq!(false, buf.temporary);
        assert_eq!(false, buf.is_temporary());

        assert_eq!(false, buf.read_only);
        assert_eq!(false, buf.is_ro());

        assert_eq!("fundamental-mode", buf.major_mode);
        assert_eq!(false, buf.dirty);
    }

    #[test]
    fn test_buffer_major_minor_modes() {
        let mut buf = Buffer::new();
        buf.major_mode = "rust-mode";
        buf.minor_modes.push("auto-wrap-mode");
        buf.minor_modes.push("spell-check-mode");
        buf.minor_modes.push("complete-me-mode");
        buf.minor_modes.push("language-server-mode");

        assert_eq!(4, buf.minor_modes.len());
        assert_eq!("rust-mode", buf.major_mode);
    }
}
<|endoftext|>


<commit_before>// only-linux: Uses Linux-only APIs

#![feature(rustc_private)]
extern crate libc;

fn main() {
    let mut buf = [0u8; 5];
    unsafe {
		assert_eq!(libc::syscall(libc::SYS_getrandom, 0 as *mut libc::c_void, 0 as libc::size_t, 0 as libc::c_uint), 0);
        assert_eq!(libc::syscall(libc::SYS_getrandom, buf.as_mut_ptr() as *mut libc::c_void, 5 as libc::size_t, 0 as libc::c_uint), 5);

        assert_eq!(libc::getrandom(0 as *mut libc::c_void, 0 as libc::size_t, 0 as libc::c_uint), 0);
        assert_eq!(libc::getrandom(buf.as_mut_ptr() as *mut libc::c_void, 5 as libc::size_t, 0 as libc::c_uint), 5);
    }
}
<commit_msg>Fix identation<commit_after>// only-linux: Uses Linux-only APIs

#![feature(rustc_private)]
extern crate libc;

fn main() {
    let mut buf = [0u8; 5];
    unsafe {
        assert_eq!(libc::syscall(libc::SYS_getrandom, 0 as *mut libc::c_void, 0 as libc::size_t, 0 as libc::c_uint), 0);
        assert_eq!(libc::syscall(libc::SYS_getrandom, buf.as_mut_ptr() as *mut libc::c_void, 5 as libc::size_t, 0 as libc::c_uint), 5);

        assert_eq!(libc::getrandom(0 as *mut libc::c_void, 0 as libc::size_t, 0 as libc::c_uint), 0);
        assert_eq!(libc::getrandom(buf.as_mut_ptr() as *mut libc::c_void, 5 as libc::size_t, 0 as libc::c_uint), 5);
    }
}
<|endoftext|>


<commit_before>// Test various stacked-borrows-related things.
fn main() {
    deref_partially_dangling_raw();
    read_does_not_invalidate1();
    read_does_not_invalidate2();
    ref_raw_int_raw();
}

// Deref a raw ptr to access a field of a large struct, where the field
// is allocated but not the entire struct is.
// For now, we want to allow this.
fn deref_partially_dangling_raw() {
    let x = (1, 13);
    let xptr = &x as *const _ as *const (i32, i32, i32);
    let val = unsafe { (*xptr).1 };
    assert_eq!(val, 13);
}

// Make sure that reading from an `&mut` does, like reborrowing to `&`,
// NOT invalidate other reborrows.
fn read_does_not_invalidate1() {
    fn foo(x: &mut (i32, i32)) -> &i32 {
        let xraw = x as *mut (i32, i32);
        let ret = unsafe { &(*xraw).1 };
        let _val = x.1; // we just read, this does NOT invalidate the reborrows.
        ret
    }
    assert_eq!(*foo(&mut (1, 2)), 2);
}
// Same as above, but this time we first create a raw, then read from `&mut`
// and then freeze from the raw.
fn read_does_not_invalidate2() {
    fn foo(x: &mut (i32, i32)) -> &i32 {
        let xraw = x as *mut (i32, i32);
        let _val = x.1; // we just read, this does NOT invalidate the raw reborrow.
        let ret = unsafe { &(*xraw).1 };
        ret
    }
    assert_eq!(*foo(&mut (1, 2)), 2);
}

// Just to make sure that casting a ref to raw, to int and back to raw
// and only then using it works.  This rules out ideas like "do escape-to-raw lazily":
// After casting to int and back, we lost the tag that could have let us do that.
fn ref_raw_int_raw() {
    let mut x = 3;
    let xref = &mut x;
    let xraw = xref as *mut i32 as usize as *mut i32;
    assert_eq!(unsafe { *xraw }, 3);
}
<commit_msg>test for special things that are now possible<commit_after>// Test various stacked-borrows-related things.
fn main() {
    deref_partially_dangling_raw();
    read_does_not_invalidate1();
    read_does_not_invalidate2();
    ref_raw_int_raw();
    mut_shr_raw();
    mut_raw_then_mut_shr();
}

// Deref a raw ptr to access a field of a large struct, where the field
// is allocated but not the entire struct is.
// For now, we want to allow this.
fn deref_partially_dangling_raw() {
    let x = (1, 13);
    let xptr = &x as *const _ as *const (i32, i32, i32);
    let val = unsafe { (*xptr).1 };
    assert_eq!(val, 13);
}

// Make sure that reading from an `&mut` does, like reborrowing to `&`,
// NOT invalidate other reborrows.
fn read_does_not_invalidate1() {
    fn foo(x: &mut (i32, i32)) -> &i32 {
        let xraw = x as *mut (i32, i32);
        let ret = unsafe { &(*xraw).1 };
        let _val = x.1; // we just read, this does NOT invalidate the reborrows.
        ret
    }
    assert_eq!(*foo(&mut (1, 2)), 2);
}
// Same as above, but this time we first create a raw, then read from `&mut`
// and then freeze from the raw.
fn read_does_not_invalidate2() {
    fn foo(x: &mut (i32, i32)) -> &i32 {
        let xraw = x as *mut (i32, i32);
        let _val = x.1; // we just read, this does NOT invalidate the raw reborrow.
        let ret = unsafe { &(*xraw).1 };
        ret
    }
    assert_eq!(*foo(&mut (1, 2)), 2);
}

// Just to make sure that casting a ref to raw, to int and back to raw
// and only then using it works.  This rules out ideas like "do escape-to-raw lazily":
// After casting to int and back, we lost the tag that could have let us do that.
fn ref_raw_int_raw() {
    let mut x = 3;
    let xref = &mut x;
    let xraw = xref as *mut i32 as usize as *mut i32;
    assert_eq!(unsafe { *xraw }, 3);
}

// Creating a raw from a `&mut` through an `&` works, even if we
// write through that raw.
fn mut_shr_raw() {
    let mut x = 2;
    {
        let xref = &mut x;
        let xraw = &*xref as *const i32 as *mut i32;
        unsafe { *xraw = 4; }
    }
    assert_eq!(x, 4);
}

// Escape a mut to raw, then share the same mut and use the share, then the raw.
// That should work.
fn mut_raw_then_mut_shr() {
    let mut x = 2;
    {
        let xref = &mut x;
        let xraw = &mut *xref as *mut _;
        let xshr = &*xref;
        assert_eq!(*xshr, 2);
        unsafe { *xraw = 4; }
    }
    assert_eq!(x, 4);
}
<|endoftext|>


<commit_before>/// Editor options.
pub struct Options {
    /// Autoindent on line breaks?
    pub autoindent: bool,
    /// Debug mode.
    pub debug: bool,
    /// Highlight.
    pub highlight: bool,
    /// Line marker (dimmed background of the current line).
    pub line_marker: bool,
}

impl Options {
    /// Create new default options
    pub fn new() -> Self {
        Options {
            autoindent: true,
            debug: true, // TODO: Let this be `true` only in debug compilation cfg
            highlight: true,
            line_marker: true,
        }
    }

    /// Get the given option as a mutable reference
    pub fn get_mut(&mut self, name: &str) -> Option<&mut bool> {
        match name {
            "autoindent" | "ai" => Some(&mut self.autoindent),
            "debug" | "debug_mode" => Some(&mut self.debug),
            "hightlight" | "hl" => Some(&mut self.highlight),
            "line_marker" | "linemarker" | "linemark" | "lm" => Some(&mut self.line_marker),
            _ => None,
        }
    }

    /// Get a given option
    pub fn get(&self, name: &str) -> Option<bool> {
        match name {
            "autoindent" | "ai" => Some(self.autoindent),
            "debug" | "debug_mode" => Some(self.debug),
            "hightlight" | "hl" => Some(self.highlight),
            "line_marker" | "linemarker" | "linemark" | "lm" => Some(self.line_marker),
            _ => None,
        }
    }

    /// Set a given option (mark it as active)
    pub fn set(&mut self, name: &str) -> Result<(), ()> {
        match self.get_mut(name) {
            Some(x) => {
                *x = true;
                Ok(())
            }
            None => Err(()),
        }
    }
    /// Unset a given option (mark it as inactive)
    pub fn unset(&mut self, name: &str) -> Result<(), ()> {
        match self.get_mut(name) {
            Some(x) => {
                *x = false;
                Ok(())
            }
            None => Err(()),
        }
    }
    /// Toggle a given option
    pub fn toggle(&mut self, name: &str) -> Result<(), ()> {
        match self.get_mut(name) {
            Some(x) => {
                *x = !*x;
                Ok(())
            }
            None => Err(()),
        }
    }
}
<commit_msg>fixing highlight option typo<commit_after>/// Editor options.
pub struct Options {
    /// Autoindent on line breaks?
    pub autoindent: bool,
    /// Debug mode.
    pub debug: bool,
    /// Highlight.
    pub highlight: bool,
    /// Line marker (dimmed background of the current line).
    pub line_marker: bool,
}

impl Options {
    /// Create new default options
    pub fn new() -> Self {
        Options {
            autoindent: true,
            debug: true, // TODO: Let this be `true` only in debug compilation cfg
            highlight: true,
            line_marker: true,
        }
    }

    /// Get the given option as a mutable reference
    pub fn get_mut(&mut self, name: &str) -> Option<&mut bool> {
        match name {
            "autoindent" | "ai" => Some(&mut self.autoindent),
            "debug" | "debug_mode" => Some(&mut self.debug),
            "highlight" | "hl" => Some(&mut self.highlight),
            "line_marker" | "linemarker" | "linemark" | "lm" => Some(&mut self.line_marker),
            _ => None,
        }
    }

    /// Get a given option
    pub fn get(&self, name: &str) -> Option<bool> {
        match name {
            "autoindent" | "ai" => Some(self.autoindent),
            "debug" | "debug_mode" => Some(self.debug),
            "highlight" | "hl" => Some(self.highlight),
            "line_marker" | "linemarker" | "linemark" | "lm" => Some(self.line_marker),
            _ => None,
        }
    }

    /// Set a given option (mark it as active)
    pub fn set(&mut self, name: &str) -> Result<(), ()> {
        match self.get_mut(name) {
            Some(x) => {
                *x = true;
                Ok(())
            }
            None => Err(()),
        }
    }
    /// Unset a given option (mark it as inactive)
    pub fn unset(&mut self, name: &str) -> Result<(), ()> {
        match self.get_mut(name) {
            Some(x) => {
                *x = false;
                Ok(())
            }
            None => Err(()),
        }
    }
    /// Toggle a given option
    pub fn toggle(&mut self, name: &str) -> Result<(), ()> {
        match self.get_mut(name) {
            Some(x) => {
                *x = !*x;
                Ok(())
            }
            None => Err(()),
        }
    }
}
<|endoftext|>