<commit_before>//! Support and tests related to the dependency management for multi-image
//! support.

use crate::image::ImageVersion;

pub trait Depender {
    /// Generate a version for this particular image.  The slot indicates
    /// which slot this is being put in.
    fn my_version(&self, offset: usize, slot: usize) -> ImageVersion;

    /// Return dependencies for this image/slot combination.
    fn my_deps(&self, offset: usize, slot: usize) -> Vec<ImageVersion>;

    /// Return the image ID of the other version.
    fn other_id(&self) -> u8;
}

/// A boring image is used when we aren't testing dependencies.  There will
/// be meaningful version numbers.  The size field is the image number we
/// are.
pub struct BoringDep(pub usize);

impl Depender for BoringDep {
    fn my_version(&self, _offset: usize, slot: usize) -> ImageVersion {
        ImageVersion::new_synthetic(self.0 as u8, slot as u8, 0)
    }

    fn my_deps(&self, _offset: usize, _slot: usize) -> Vec<ImageVersion> {
        vec![]
    }

    fn other_id(&self) -> u8 {
        0
    }
}

/// An individual test of the dependency mechanism describes one of the
/// possibilities for the dependency information for each image, and what
/// the expected outcome is.
#[derive(Clone, Debug)]
pub struct DepTest {
    /// What kinds of dependency should be installed in the image.
    pub depends: [DepType; 2],

    /// What is the expected outcome of the upgrade.
    pub upgrades: [UpgradeInfo; 2],
}

/// Describes the various types of dependency information that can be
/// provided.
#[derive(Clone, Debug)]
pub enum DepType {
    /// Do not include dependency information
    Nothing,
    /// Provide dependency information that matches the other image.
    Correct,
    /// Provide dependency information describing something newer than the
    /// other image.
    Newer,
}

/// Describes what our expectation is for an upgrade.
#[derive(Clone, Debug)]
pub enum UpgradeInfo {
    /// The current version should be held.
    Held,
    /// The image should be upgraded
    Upgraded,
}

/// A "test" that gives no dependency information.
pub static NO_DEPS: DepTest = DepTest {
    depends: [DepType::Nothing, DepType::Nothing],
    upgrades: [UpgradeInfo::Upgraded, UpgradeInfo::Upgraded],
};

/// A PairDep describes the dependencies between two pairs.
pub struct PairDep {
    /// The image number of this image.
    number: usize,

    test: DepTest,
}

impl PairDep {
    pub fn new(total_image: usize, my_image: usize, deps: &DepTest) -> PairDep {
        if total_image != 2 {
            panic!("PairDep only works when there are two images");
        }

        PairDep {
            number: my_image,
            test: deps.clone(),
        }
    }
}

impl Depender for PairDep {
    fn my_version(&self, _offset: usize, slot: usize) -> ImageVersion {
        ImageVersion::new_synthetic(self.number as u8, slot as u8, 0)
    }

    fn my_deps(&self, _offset: usize, slot: usize) -> Vec<ImageVersion> {
        match self.test.depends[self.number] {
            DepType::Nothing => vec![],
            DepType::Correct => vec![
                ImageVersion::new_synthetic(self.other_id(), slot as u8, 0)
            ],
            DepType::Newer => vec![
                ImageVersion::new_synthetic(self.other_id(), slot as u8, 1)
            ],
        }
    }

    fn other_id(&self) -> u8 {
        (1 - self.number) as u8
    }
}

impl ImageVersion {
    /// Generate an image version based on some key information.  The image
    /// number influences the major version number (by an arbitrary factor),
    /// and the slot affects the major number on the build_number.  The minor
    /// number can also be given to force numbers to be different.
    fn new_synthetic(image_id: u8, slot: u8, minor: u8) -> ImageVersion {
        ImageVersion {
            major: image_id * 20 + slot,
            minor: minor,
            revision: 1,
            build_num: slot as u32,
        }
    }
}
<commit_msg>sim: Derive PartialEq and Eq for UpgradeInfo<commit_after>//! Support and tests related to the dependency management for multi-image
//! support.

use crate::image::ImageVersion;

pub trait Depender {
    /// Generate a version for this particular image.  The slot indicates
    /// which slot this is being put in.
    fn my_version(&self, offset: usize, slot: usize) -> ImageVersion;

    /// Return dependencies for this image/slot combination.
    fn my_deps(&self, offset: usize, slot: usize) -> Vec<ImageVersion>;

    /// Return the image ID of the other version.
    fn other_id(&self) -> u8;
}

/// A boring image is used when we aren't testing dependencies.  There will
/// be meaningful version numbers.  The size field is the image number we
/// are.
pub struct BoringDep(pub usize);

impl Depender for BoringDep {
    fn my_version(&self, _offset: usize, slot: usize) -> ImageVersion {
        ImageVersion::new_synthetic(self.0 as u8, slot as u8, 0)
    }

    fn my_deps(&self, _offset: usize, _slot: usize) -> Vec<ImageVersion> {
        vec![]
    }

    fn other_id(&self) -> u8 {
        0
    }
}

/// An individual test of the dependency mechanism describes one of the
/// possibilities for the dependency information for each image, and what
/// the expected outcome is.
#[derive(Clone, Debug)]
pub struct DepTest {
    /// What kinds of dependency should be installed in the image.
    pub depends: [DepType; 2],

    /// What is the expected outcome of the upgrade.
    pub upgrades: [UpgradeInfo; 2],
}

/// Describes the various types of dependency information that can be
/// provided.
#[derive(Clone, Debug)]
pub enum DepType {
    /// Do not include dependency information
    Nothing,
    /// Provide dependency information that matches the other image.
    Correct,
    /// Provide dependency information describing something newer than the
    /// other image.
    Newer,
}

/// Describes what our expectation is for an upgrade.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum UpgradeInfo {
    /// The current version should be held.
    Held,
    /// The image should be upgraded
    Upgraded,
}

/// A "test" that gives no dependency information.
pub static NO_DEPS: DepTest = DepTest {
    depends: [DepType::Nothing, DepType::Nothing],
    upgrades: [UpgradeInfo::Upgraded, UpgradeInfo::Upgraded],
};

/// A PairDep describes the dependencies between two pairs.
pub struct PairDep {
    /// The image number of this image.
    number: usize,

    test: DepTest,
}

impl PairDep {
    pub fn new(total_image: usize, my_image: usize, deps: &DepTest) -> PairDep {
        if total_image != 2 {
            panic!("PairDep only works when there are two images");
        }

        PairDep {
            number: my_image,
            test: deps.clone(),
        }
    }
}

impl Depender for PairDep {
    fn my_version(&self, _offset: usize, slot: usize) -> ImageVersion {
        ImageVersion::new_synthetic(self.number as u8, slot as u8, 0)
    }

    fn my_deps(&self, _offset: usize, slot: usize) -> Vec<ImageVersion> {
        match self.test.depends[self.number] {
            DepType::Nothing => vec![],
            DepType::Correct => vec![
                ImageVersion::new_synthetic(self.other_id(), slot as u8, 0)
            ],
            DepType::Newer => vec![
                ImageVersion::new_synthetic(self.other_id(), slot as u8, 1)
            ],
        }
    }

    fn other_id(&self) -> u8 {
        (1 - self.number) as u8
    }
}

impl ImageVersion {
    /// Generate an image version based on some key information.  The image
    /// number influences the major version number (by an arbitrary factor),
    /// and the slot affects the major number on the build_number.  The minor
    /// number can also be given to force numbers to be different.
    fn new_synthetic(image_id: u8, slot: u8, minor: u8) -> ImageVersion {
        ImageVersion {
            major: image_id * 20 + slot,
            minor: minor,
            revision: 1,
            build_num: slot as u32,
        }
    }
}
<|endoftext|>


<commit_before>//! Proc Macro Expander stub

use crate::{db::AstDatabase, LazyMacroId, MacroCallKind, MacroCallLoc};
use ra_db::CrateId;

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct ProcMacroExpander {
    krate: CrateId,
}

impl ProcMacroExpander {
    pub fn new(krate: CrateId) -> ProcMacroExpander {
        ProcMacroExpander { krate }
    }

    pub fn expand(
        &self,
        db: &dyn AstDatabase,
        id: LazyMacroId,
        _tt: &tt::Subtree,
    ) -> Result<tt::Subtree, mbe::ExpandError> {
        let loc: MacroCallLoc = db.lookup_intern_macro(id);
        let name = match loc.kind {
            MacroCallKind::FnLike(_) => return Err(mbe::ExpandError::ConversionError),
            MacroCallKind::Attr(_, name) => name,
        };

        dbg!(name);

        unimplemented!()
    }
}
<commit_msg>Use dummy implementation<commit_after>//! Proc Macro Expander stub

use crate::{db::AstDatabase, LazyMacroId, MacroCallKind, MacroCallLoc};
use ra_db::CrateId;

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct ProcMacroExpander {
    krate: CrateId,
}

impl ProcMacroExpander {
    pub fn new(krate: CrateId) -> ProcMacroExpander {
        ProcMacroExpander { krate }
    }

    pub fn expand(
        &self,
        db: &dyn AstDatabase,
        id: LazyMacroId,
        _tt: &tt::Subtree,
    ) -> Result<tt::Subtree, mbe::ExpandError> {
        let loc: MacroCallLoc = db.lookup_intern_macro(id);
        let name = match loc.kind {
            MacroCallKind::FnLike(_) => return Err(mbe::ExpandError::ConversionError),
            MacroCallKind::Attr(_, name) => name,
        };

        log::debug!("Proc-macro-expanding name = {}", name);

        // Return nothing for now
        return Ok(tt::Subtree::default());
    }
}
<|endoftext|>


<commit_before>//! Disassembly calling function for most targets.

use crate::Function;
use std::{collections::HashSet, env, process::Command, str};

// Extracts the "shim" name from the `symbol`.
fn normalize(mut symbol: &str) -> String {
    // Remove trailing colon:
    if symbol.ends_with(':') {
        symbol = &symbol[..symbol.len() - 1];
    }
    if symbol.ends_with('>') {
        symbol = &symbol[..symbol.len() - 1];
    }
    if let Some(idx) = symbol.find('<') {
        symbol = &symbol[idx + 1..];
    }

    let mut symbol = rustc_demangle::demangle(symbol).to_string();
    symbol = match symbol.rfind("::h") {
        Some(i) => symbol[..i].to_string(),
        None => symbol.to_string(),
    };

    // Remove Rust paths
    if let Some(last_colon) = symbol.rfind(':') {
        symbol = (&symbol[last_colon + 1..]).to_string();
    }

    // Normalize to no leading underscore to handle platforms that may
    // inject extra ones in symbol names.
    while symbol.starts_with('_') {
        symbol.remove(0);
    }
    // Windows/x86 has a suffix such as @@4.
    if let Some(idx) = symbol.find("@@") {
        symbol = (&symbol[..idx]).to_string();
    }
    symbol
}

pub(crate) fn disassemble_myself() -> HashSet<Function> {
    let me = env::current_exe().expect("failed to get current exe");

    let disassembly = if cfg!(target_os = "windows") && cfg!(target_env = "msvc") {
        let target = if cfg!(target_arch = "x86_64") {
            "x86_64-pc-windows-msvc"
        } else if cfg!(target_arch = "x86") {
            "i686-pc-windows-msvc"
        } else {
            panic!("disassembly unimplemented")
        };
        let mut cmd = cc::windows_registry::find(target, "dumpbin.exe")
            .expect("failed to find `dumpbin` tool");
        let output = cmd
            .arg("/DISASM")
            .arg(&me)
            .output()
            .expect("failed to execute dumpbin");
        println!(
            "{}\n{}",
            output.status,
            String::from_utf8_lossy(&output.stderr)
        );
        assert!(output.status.success());
        // Windows does not return valid UTF-8 output:
        String::from_utf8_lossy(Vec::leak(output.stdout))
    } else if cfg!(target_os = "windows") {
        panic!("disassembly unimplemented")
    } else {
        let objdump = env::var("OBJDUMP").unwrap_or_else(|_| "objdump".to_string());
        let add_args = if cfg!(target_os = "macos") && cfg!(target_arch = "aarch64") {
            // Target features need to be enabled for LLVM objdump on Macos ARM64
            vec!["--mattr=+v8.6a,+crypto,+tme"]
        } else {
            vec![]
        };
        let output = Command::new(objdump.clone())
            .arg("--disassemble")
            .arg("--no-show-raw-insn")
            .args(add_args)
            .arg(&me)
            .output()
            .unwrap_or_else(|_| panic!("failed to execute objdump. OBJDUMP={}", objdump));
        println!(
            "{}\n{}",
            output.status,
            String::from_utf8_lossy(&output.stderr)
        );
        assert!(output.status.success());

        String::from_utf8_lossy(Vec::leak(output.stdout))
    };

    parse(&disassembly)
}

fn parse(output: &str) -> HashSet<Function> {
    let mut lines = output.lines();

    println!(
        "First 100 lines of the disassembly input containing {} lines:",
        lines.clone().count()
    );
    for line in output.lines().take(100) {
        println!("{}", line);
    }

    let mut functions = HashSet::new();
    let mut cached_header = None;
    while let Some(header) = cached_header.take().or_else(|| lines.next()) {
        if !header.ends_with(':') || !header.contains("stdarch_test_shim") {
            continue;
        }
        eprintln!("header: {}", header);
        let symbol = normalize(header);
        eprintln!("normalized symbol: {}", symbol);
        let mut instructions = Vec::new();
        while let Some(instruction) = lines.next() {
            if instruction.ends_with(':') {
                cached_header = Some(instruction);
                break;
            }
            if instruction.is_empty() {
                cached_header = None;
                break;
            }
            let parts = if cfg!(target_os = "macos") {
                // Each line of instructions should look like:
                //
                //      $addr    $instruction...
                instruction
                    .split_whitespace()
                    .skip(1)
                    .map(std::string::ToString::to_string)
                    .collect::<Vec<String>>()
            } else if cfg!(target_env = "msvc") {
                // Each line looks like:
                //
                // >  $addr: ab cd ef     $instr..
                // >         00 12          # this line os optional
                if instruction.starts_with("       ") {
                    continue;
                }
                instruction
                    .split_whitespace()
                    .skip(1)
                    .skip_while(|s| s.len() == 2 && usize::from_str_radix(s, 16).is_ok())
                    .map(std::string::ToString::to_string)
                    .skip_while(|s| *s == "lock") // skip x86-specific prefix
                    .collect::<Vec<String>>()
            } else {
                // objdump with --no-show-raw-insn
                // Each line of instructions should look like:
                //
                //      $rel_offset:       $instruction...
                instruction
                    .split_whitespace()
                    .skip(1)
                    .skip_while(|s| *s == "lock") // skip x86-specific prefix
                    .map(std::string::ToString::to_string)
                    .collect::<Vec<String>>()
            };
            instructions.push(parts.join(" "));
        }
        let function = Function {
            name: symbol,
            instrs: instructions,
        };
        assert!(functions.insert(function));
    }

    eprintln!("all found functions dump:");
    for k in &functions {
        eprintln!("  f: {}", k.name);
    }

    functions
}
<commit_msg>remove assembly parsing special case for otool output (no longer needed)<commit_after>//! Disassembly calling function for most targets.

use crate::Function;
use std::{collections::HashSet, env, process::Command, str};

// Extracts the "shim" name from the `symbol`.
fn normalize(mut symbol: &str) -> String {
    // Remove trailing colon:
    if symbol.ends_with(':') {
        symbol = &symbol[..symbol.len() - 1];
    }
    if symbol.ends_with('>') {
        symbol = &symbol[..symbol.len() - 1];
    }
    if let Some(idx) = symbol.find('<') {
        symbol = &symbol[idx + 1..];
    }

    let mut symbol = rustc_demangle::demangle(symbol).to_string();
    symbol = match symbol.rfind("::h") {
        Some(i) => symbol[..i].to_string(),
        None => symbol.to_string(),
    };

    // Remove Rust paths
    if let Some(last_colon) = symbol.rfind(':') {
        symbol = (&symbol[last_colon + 1..]).to_string();
    }

    // Normalize to no leading underscore to handle platforms that may
    // inject extra ones in symbol names.
    while symbol.starts_with('_') {
        symbol.remove(0);
    }
    // Windows/x86 has a suffix such as @@4.
    if let Some(idx) = symbol.find("@@") {
        symbol = (&symbol[..idx]).to_string();
    }
    symbol
}

pub(crate) fn disassemble_myself() -> HashSet<Function> {
    let me = env::current_exe().expect("failed to get current exe");

    let disassembly = if cfg!(target_os = "windows") && cfg!(target_env = "msvc") {
        let target = if cfg!(target_arch = "x86_64") {
            "x86_64-pc-windows-msvc"
        } else if cfg!(target_arch = "x86") {
            "i686-pc-windows-msvc"
        } else {
            panic!("disassembly unimplemented")
        };
        let mut cmd = cc::windows_registry::find(target, "dumpbin.exe")
            .expect("failed to find `dumpbin` tool");
        let output = cmd
            .arg("/DISASM")
            .arg(&me)
            .output()
            .expect("failed to execute dumpbin");
        println!(
            "{}\n{}",
            output.status,
            String::from_utf8_lossy(&output.stderr)
        );
        assert!(output.status.success());
        // Windows does not return valid UTF-8 output:
        String::from_utf8_lossy(Vec::leak(output.stdout))
    } else if cfg!(target_os = "windows") {
        panic!("disassembly unimplemented")
    } else {
        let objdump = env::var("OBJDUMP").unwrap_or_else(|_| "objdump".to_string());
        let add_args = if cfg!(target_os = "macos") && cfg!(target_arch = "aarch64") {
            // Target features need to be enabled for LLVM objdump on Macos ARM64
            vec!["--mattr=+v8.6a,+crypto,+tme"]
        } else {
            vec![]
        };
        let output = Command::new(objdump.clone())
            .arg("--disassemble")
            .arg("--no-show-raw-insn")
            .args(add_args)
            .arg(&me)
            .output()
            .unwrap_or_else(|_| panic!("failed to execute objdump. OBJDUMP={}", objdump));
        println!(
            "{}\n{}",
            output.status,
            String::from_utf8_lossy(&output.stderr)
        );
        assert!(output.status.success());

        String::from_utf8_lossy(Vec::leak(output.stdout))
    };

    parse(&disassembly)
}

fn parse(output: &str) -> HashSet<Function> {
    let mut lines = output.lines();

    println!(
        "First 100 lines of the disassembly input containing {} lines:",
        lines.clone().count()
    );
    for line in output.lines().take(100) {
        println!("{}", line);
    }

    let mut functions = HashSet::new();
    let mut cached_header = None;
    while let Some(header) = cached_header.take().or_else(|| lines.next()) {
        if !header.ends_with(':') || !header.contains("stdarch_test_shim") {
            continue;
        }
        eprintln!("header: {}", header);
        let symbol = normalize(header);
        eprintln!("normalized symbol: {}", symbol);
        let mut instructions = Vec::new();
        while let Some(instruction) = lines.next() {
            if instruction.ends_with(':') {
                cached_header = Some(instruction);
                break;
            }
            if instruction.is_empty() {
                cached_header = None;
                break;
            }
            let parts = if cfg!(target_env = "msvc") {
                // Each line looks like:
                //
                // >  $addr: ab cd ef     $instr..
                // >         00 12          # this line os optional
                if instruction.starts_with("       ") {
                    continue;
                }
                instruction
                    .split_whitespace()
                    .skip(1)
                    .skip_while(|s| s.len() == 2 && usize::from_str_radix(s, 16).is_ok())
                    .map(std::string::ToString::to_string)
                    .skip_while(|s| *s == "lock") // skip x86-specific prefix
                    .collect::<Vec<String>>()
            } else {
                // objdump with --no-show-raw-insn
                // Each line of instructions should look like:
                //
                //      $rel_offset:       $instruction...
                instruction
                    .split_whitespace()
                    .skip(1)
                    .skip_while(|s| *s == "lock") // skip x86-specific prefix
                    .map(std::string::ToString::to_string)
                    .collect::<Vec<String>>()
            };
            instructions.push(parts.join(" "));
        }
        let function = Function {
            name: symbol,
            instrs: instructions,
        };
        assert!(functions.insert(function));
    }

    eprintln!("all found functions dump:");
    for k in &functions {
        eprintln!("  f: {}", k.name);
    }

    functions
}
<|endoftext|>


<commit_before>use crate::utils::{get_trait_def_id, span_lint, trait_ref_of_method};
use if_chain::if_chain;
use rustc_hir as hir;
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
    /// **What it does:** Lints for suspicious operations in impls of arithmetic operators, e.g.
    /// subtracting elements in an Add impl.
    ///
    /// **Why this is bad?** This is probably a typo or copy-and-paste error and not intended.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```ignore
    /// impl Add for Foo {
    ///     type Output = Foo;
    ///
    ///     fn add(self, other: Foo) -> Foo {
    ///         Foo(self.0 - other.0)
    ///     }
    /// }
    /// ```
    pub SUSPICIOUS_ARITHMETIC_IMPL,
    correctness,
    "suspicious use of operators in impl of arithmetic trait"
}

declare_clippy_lint! {
    /// **What it does:** Lints for suspicious operations in impls of OpAssign, e.g.
    /// subtracting elements in an AddAssign impl.
    ///
    /// **Why this is bad?** This is probably a typo or copy-and-paste error and not intended.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```ignore
    /// impl AddAssign for Foo {
    ///     fn add_assign(&mut self, other: Foo) {
    ///         *self = *self - other;
    ///     }
    /// }
    /// ```
    pub SUSPICIOUS_OP_ASSIGN_IMPL,
    correctness,
    "suspicious use of operators in impl of OpAssign trait"
}

declare_lint_pass!(SuspiciousImpl => [SUSPICIOUS_ARITHMETIC_IMPL, SUSPICIOUS_OP_ASSIGN_IMPL]);

impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
        if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind {
            match binop.node {
                hir::BinOpKind::Eq
                | hir::BinOpKind::Lt
                | hir::BinOpKind::Le
                | hir::BinOpKind::Ne
                | hir::BinOpKind::Ge
                | hir::BinOpKind::Gt => return,
                _ => {},
            }

            // Check for more than one binary operation in the implemented function
            // Linting when multiple operations are involved can result in false positives
            if_chain! {
                let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id);
                if let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get(parent_fn);
                if let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind;
                let body = cx.tcx.hir().body(body_id);
                let mut visitor = BinaryExprVisitor { nb_binops: 0 };

                then {
                    walk_expr(&mut visitor, &body.value);
                    if visitor.nb_binops > 1 {
                        return;
                    }
                }
            }

            if let Some(impl_trait) = check_binop(
                cx,
                expr,
                binop.node,
                &["Add", "Sub", "Mul", "Div"],
                &[
                    hir::BinOpKind::Add,
                    hir::BinOpKind::Sub,
                    hir::BinOpKind::Mul,
                    hir::BinOpKind::Div,
                ],
            ) {
                span_lint(
                    cx,
                    SUSPICIOUS_ARITHMETIC_IMPL,
                    binop.span,
                    &format!("suspicious use of binary operator in `{}` impl", impl_trait),
                );
            }

            if let Some(impl_trait) = check_binop(
                cx,
                expr,
                binop.node,
                &[
                    "AddAssign",
                    "SubAssign",
                    "MulAssign",
                    "DivAssign",
                    "BitAndAssign",
                    "BitOrAssign",
                    "BitXorAssign",
                    "RemAssign",
                    "ShlAssign",
                    "ShrAssign",
                ],
                &[
                    hir::BinOpKind::Add,
                    hir::BinOpKind::Sub,
                    hir::BinOpKind::Mul,
                    hir::BinOpKind::Div,
                    hir::BinOpKind::BitAnd,
                    hir::BinOpKind::BitOr,
                    hir::BinOpKind::BitXor,
                    hir::BinOpKind::Rem,
                    hir::BinOpKind::Shl,
                    hir::BinOpKind::Shr,
                ],
            ) {
                span_lint(
                    cx,
                    SUSPICIOUS_OP_ASSIGN_IMPL,
                    binop.span,
                    &format!("suspicious use of binary operator in `{}` impl", impl_trait),
                );
            }
        }
    }
}

fn check_binop(
    cx: &LateContext<'_>,
    expr: &hir::Expr<'_>,
    binop: hir::BinOpKind,
    traits: &[&'static str],
    expected_ops: &[hir::BinOpKind],
) -> Option<&'static str> {
    let mut trait_ids = vec![];
    let [krate, module] = crate::utils::paths::OPS_MODULE;

    for &t in traits {
        let path = [krate, module, t];
        if let Some(trait_id) = get_trait_def_id(cx, &path) {
            trait_ids.push(trait_id);
        } else {
            return None;
        }
    }

    // Get the actually implemented trait
    let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id);

    if_chain! {
        if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn);
        if let Some(idx) = trait_ids.iter().position(|&tid| tid == trait_ref.path.res.def_id());
        if binop != expected_ops[idx];
        then{
            return Some(traits[idx])
        }
    }

    None
}

struct BinaryExprVisitor {
    nb_binops: u32,
}

impl<'tcx> Visitor<'tcx> for BinaryExprVisitor {
    type Map = Map<'tcx>;

    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
        match expr.kind {
            hir::ExprKind::Binary(..)
            | hir::ExprKind::Unary(hir::UnOp::UnNot | hir::UnOp::UnNeg, _)
            | hir::ExprKind::AssignOp(..) => self.nb_binops += 1,
            _ => {},
        }

        walk_expr(self, expr);
    }

    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::None
    }
}
<commit_msg>Add the other overloadable operations to suspicious_arithmetic_impl<commit_after>use crate::utils::{get_trait_def_id, span_lint, trait_ref_of_method};
use if_chain::if_chain;
use rustc_hir as hir;
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
    /// **What it does:** Lints for suspicious operations in impls of arithmetic operators, e.g.
    /// subtracting elements in an Add impl.
    ///
    /// **Why this is bad?** This is probably a typo or copy-and-paste error and not intended.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```ignore
    /// impl Add for Foo {
    ///     type Output = Foo;
    ///
    ///     fn add(self, other: Foo) -> Foo {
    ///         Foo(self.0 - other.0)
    ///     }
    /// }
    /// ```
    pub SUSPICIOUS_ARITHMETIC_IMPL,
    correctness,
    "suspicious use of operators in impl of arithmetic trait"
}

declare_clippy_lint! {
    /// **What it does:** Lints for suspicious operations in impls of OpAssign, e.g.
    /// subtracting elements in an AddAssign impl.
    ///
    /// **Why this is bad?** This is probably a typo or copy-and-paste error and not intended.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```ignore
    /// impl AddAssign for Foo {
    ///     fn add_assign(&mut self, other: Foo) {
    ///         *self = *self - other;
    ///     }
    /// }
    /// ```
    pub SUSPICIOUS_OP_ASSIGN_IMPL,
    correctness,
    "suspicious use of operators in impl of OpAssign trait"
}

declare_lint_pass!(SuspiciousImpl => [SUSPICIOUS_ARITHMETIC_IMPL, SUSPICIOUS_OP_ASSIGN_IMPL]);

impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
        if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind {
            match binop.node {
                hir::BinOpKind::Eq
                | hir::BinOpKind::Lt
                | hir::BinOpKind::Le
                | hir::BinOpKind::Ne
                | hir::BinOpKind::Ge
                | hir::BinOpKind::Gt => return,
                _ => {},
            }

            // Check for more than one binary operation in the implemented function
            // Linting when multiple operations are involved can result in false positives
            if_chain! {
                let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id);
                if let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get(parent_fn);
                if let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind;
                let body = cx.tcx.hir().body(body_id);
                let mut visitor = BinaryExprVisitor { nb_binops: 0 };

                then {
                    walk_expr(&mut visitor, &body.value);
                    if visitor.nb_binops > 1 {
                        return;
                    }
                }
            }

            if let Some(impl_trait) = check_binop(
                cx,
                expr,
                binop.node,
                &["Add", "Sub", "Mul", "Div", "Rem", "BitAnd", "BitOr", "BitXor", "Shl", "Shr"],
                &[
                    hir::BinOpKind::Add,
                    hir::BinOpKind::Sub,
                    hir::BinOpKind::Mul,
                    hir::BinOpKind::Div,
                    hir::BinOpKind::Rem,
                    hir::BinOpKind::BitAnd,
                    hir::BinOpKind::BitOr,
                    hir::BinOpKind::BitXor,
                    hir::BinOpKind::Shl,
                    hir::BinOpKind::Shr,
                ],
            ) {
                span_lint(
                    cx,
                    SUSPICIOUS_ARITHMETIC_IMPL,
                    binop.span,
                    &format!("suspicious use of binary operator in `{}` impl", impl_trait),
                );
            }

            if let Some(impl_trait) = check_binop(
                cx,
                expr,
                binop.node,
                &[
                    "AddAssign",
                    "SubAssign",
                    "MulAssign",
                    "DivAssign",
                    "BitAndAssign",
                    "BitOrAssign",
                    "BitXorAssign",
                    "RemAssign",
                    "ShlAssign",
                    "ShrAssign",
                ],
                &[
                    hir::BinOpKind::Add,
                    hir::BinOpKind::Sub,
                    hir::BinOpKind::Mul,
                    hir::BinOpKind::Div,
                    hir::BinOpKind::BitAnd,
                    hir::BinOpKind::BitOr,
                    hir::BinOpKind::BitXor,
                    hir::BinOpKind::Rem,
                    hir::BinOpKind::Shl,
                    hir::BinOpKind::Shr,
                ],
            ) {
                span_lint(
                    cx,
                    SUSPICIOUS_OP_ASSIGN_IMPL,
                    binop.span,
                    &format!("suspicious use of binary operator in `{}` impl", impl_trait),
                );
            }
        }
    }
}

fn check_binop(
    cx: &LateContext<'_>,
    expr: &hir::Expr<'_>,
    binop: hir::BinOpKind,
    traits: &[&'static str],
    expected_ops: &[hir::BinOpKind],
) -> Option<&'static str> {
    let mut trait_ids = vec![];
    let [krate, module] = crate::utils::paths::OPS_MODULE;

    for &t in traits {
        let path = [krate, module, t];
        if let Some(trait_id) = get_trait_def_id(cx, &path) {
            trait_ids.push(trait_id);
        } else {
            return None;
        }
    }

    // Get the actually implemented trait
    let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id);

    if_chain! {
        if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn);
        if let Some(idx) = trait_ids.iter().position(|&tid| tid == trait_ref.path.res.def_id());
        if binop != expected_ops[idx];
        then{
            return Some(traits[idx])
        }
    }

    None
}

struct BinaryExprVisitor {
    nb_binops: u32,
}

impl<'tcx> Visitor<'tcx> for BinaryExprVisitor {
    type Map = Map<'tcx>;

    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
        match expr.kind {
            hir::ExprKind::Binary(..)
            | hir::ExprKind::Unary(hir::UnOp::UnNot | hir::UnOp::UnNeg, _)
            | hir::ExprKind::AssignOp(..) => self.nb_binops += 1,
            _ => {},
        }

        walk_expr(self, expr);
    }

    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::None
    }
}
<|endoftext|>


<commit_before>//! Throughout the compiler tree, there are several places which want to have
//! access to state or queries while being inside crates that are dependencies
//! of librustc_middle. To facilitate this, we have the
//! `rustc_data_structures::AtomicRef` type, which allows us to setup a global
//! static which can then be set in this file at program startup.
//!
//! See `SPAN_DEBUG` for an example of how to set things up.
//!
//! The functions in this file should fall back to the default set in their
//! origin crate when the `TyCtxt` is not present in TLS.

use rustc_errors::{Diagnostic, TRACK_DIAGNOSTICS};
use rustc_middle::ty::tls;
use std::fmt;

/// This is a callback from librustc_ast as it cannot access the implicit state
/// in librustc_middle otherwise.
fn span_debug(span: rustc_span::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    tls::with_opt(|tcx| {
        if let Some(tcx) = tcx {
            rustc_span::debug_with_source_map(span, f, tcx.sess.source_map())
        } else {
            rustc_span::default_span_debug(span, f)
        }
    })
}

/// This is a callback from librustc_ast as it cannot access the implicit state
/// in librustc_middle otherwise. It is used to when diagnostic messages are
/// emitted and stores them in the current query, if there is one.
fn track_diagnostic(diagnostic: &Diagnostic) {
    tls::with_context_opt(|icx| {
        if let Some(icx) = icx {
            if let Some(ref diagnostics) = icx.diagnostics {
                let mut diagnostics = diagnostics.lock();
                diagnostics.extend(Some(diagnostic.clone()));
            }
        }
    })
}

/// This is a callback from librustc_hir as it cannot access the implicit state
/// in librustc_middle otherwise.
fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    write!(f, "DefId({}:{}", def_id.krate, def_id.index.index())?;
    tls::with_opt(|opt_tcx| {
        if let Some(tcx) = opt_tcx {
            write!(f, " ~ {}", tcx.def_path_debug_str(def_id))?;
        }
        Ok(())
    })?;
    write!(f, ")")
}

/// Sets up the callbacks in prior crates which we want to refer to the
/// TyCtxt in.
pub fn setup_callbacks() {
    rustc_span::SPAN_DEBUG.swap(&(span_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
    rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
    TRACK_DIAGNOSTICS.swap(&(track_diagnostic as fn(&_)));
}
<commit_msg>Rollup merge of #83974 - pierwill:fix-callbacks-names, r=jyn514<commit_after>//! Throughout the compiler tree, there are several places which want to have
//! access to state or queries while being inside crates that are dependencies
//! of `rustc_middle`. To facilitate this, we have the
//! `rustc_data_structures::AtomicRef` type, which allows us to setup a global
//! static which can then be set in this file at program startup.
//!
//! See `SPAN_DEBUG` for an example of how to set things up.
//!
//! The functions in this file should fall back to the default set in their
//! origin crate when the `TyCtxt` is not present in TLS.

use rustc_errors::{Diagnostic, TRACK_DIAGNOSTICS};
use rustc_middle::ty::tls;
use std::fmt;

/// This is a callback from `rustc_ast` as it cannot access the implicit state
/// in `rustc_middle` otherwise.
fn span_debug(span: rustc_span::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    tls::with_opt(|tcx| {
        if let Some(tcx) = tcx {
            rustc_span::debug_with_source_map(span, f, tcx.sess.source_map())
        } else {
            rustc_span::default_span_debug(span, f)
        }
    })
}

/// This is a callback from `rustc_ast` as it cannot access the implicit state
/// in `rustc_middle` otherwise. It is used to when diagnostic messages are
/// emitted and stores them in the current query, if there is one.
fn track_diagnostic(diagnostic: &Diagnostic) {
    tls::with_context_opt(|icx| {
        if let Some(icx) = icx {
            if let Some(ref diagnostics) = icx.diagnostics {
                let mut diagnostics = diagnostics.lock();
                diagnostics.extend(Some(diagnostic.clone()));
            }
        }
    })
}

/// This is a callback from `rustc_hir` as it cannot access the implicit state
/// in `rustc_middle` otherwise.
fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    write!(f, "DefId({}:{}", def_id.krate, def_id.index.index())?;
    tls::with_opt(|opt_tcx| {
        if let Some(tcx) = opt_tcx {
            write!(f, " ~ {}", tcx.def_path_debug_str(def_id))?;
        }
        Ok(())
    })?;
    write!(f, ")")
}

/// Sets up the callbacks in prior crates which we want to refer to the
/// TyCtxt in.
pub fn setup_callbacks() {
    rustc_span::SPAN_DEBUG.swap(&(span_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
    rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
    TRACK_DIAGNOSTICS.swap(&(track_diagnostic as fn(&_)));
}
<|endoftext|>


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

// check-tidy: no specs after this line

use crate::dom::bindings::codegen::Bindings::TestBindingProxyBinding::TestBindingProxyMethods;
use crate::dom::bindings::reflector::Reflector;
use crate::dom::bindings::str::DOMString;
use dom_struct::dom_struct;

#[dom_struct]
pub struct TestBindingProxy {
    reflector_: Reflector,
}

impl TestBindingProxyMethods for TestBindingProxy {
    fn Length(&self) -> u32 {
        0
    }
    fn SupportedPropertyNames(&self) -> Vec<DOMString> {
        vec![]
    }
    fn GetNamedItem(&self, _: DOMString) -> DOMString {
        DOMString::new()
    }
    fn SetNamedItem(&self, _: DOMString, _: DOMString) {}
    fn GetItem(&self, _: u32) -> DOMString {
        DOMString::new()
    }
    fn SetItem(&self, _: u32, _: DOMString) {}
    fn RemoveItem(&self, _: DOMString) {}
    fn Stringifier(&self) -> DOMString {
        DOMString::new()
    }
    fn IndexedGetter(&self, _: u32) -> Option<DOMString> {
        None
    }
    fn NamedDeleter(&self, _: DOMString) {}
    fn IndexedSetter(&self, _: u32, _: DOMString) {}
    fn NamedSetter(&self, _: DOMString, _: DOMString) {}
    fn NamedGetter(&self, _: DOMString) -> Option<DOMString> {
        None
    }
}
<commit_msg>Inherit TestBinding from TestBindingProxy.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

// check-tidy: no specs after this line

use crate::dom::bindings::codegen::Bindings::TestBindingProxyBinding::TestBindingProxyMethods;
use crate::dom::bindings::str::DOMString;
use crate::dom::testbinding::TestBinding;
use dom_struct::dom_struct;

#[dom_struct]
pub struct TestBindingProxy {
    testbinding_: TestBinding,
}

impl TestBindingProxyMethods for TestBindingProxy {
    fn Length(&self) -> u32 {
        0
    }
    fn SupportedPropertyNames(&self) -> Vec<DOMString> {
        vec![]
    }
    fn GetNamedItem(&self, _: DOMString) -> DOMString {
        DOMString::new()
    }
    fn SetNamedItem(&self, _: DOMString, _: DOMString) {}
    fn GetItem(&self, _: u32) -> DOMString {
        DOMString::new()
    }
    fn SetItem(&self, _: u32, _: DOMString) {}
    fn RemoveItem(&self, _: DOMString) {}
    fn Stringifier(&self) -> DOMString {
        DOMString::new()
    }
    fn IndexedGetter(&self, _: u32) -> Option<DOMString> {
        None
    }
    fn NamedDeleter(&self, _: DOMString) {}
    fn IndexedSetter(&self, _: u32, _: DOMString) {}
    fn NamedSetter(&self, _: DOMString, _: DOMString) {}
    fn NamedGetter(&self, _: DOMString) -> Option<DOMString> {
        None
    }
}
<|endoftext|>


<commit_before>use autograd::{Function, FuncIntf, FuncDelegate, FIWrap};
use tensor::{OptTensorKindList, TensorKindList};

impl_func!(LinearF);

impl FuncIntf for LinearF {
    fn forward(&mut self, input_list: &mut TensorKindList) -> TensorKindList {
        self.save_for_backward(input_list);
        let (input, weight) = (input_list.remove(0), input_list.remove(0));
        let mut output = input.new((input.size()[0], weight.size()[0]));
        output.addmm_(0, 1, &input, &weight.t());
        if input_list.len() != 0 {
            let bias = input_list.remove(0).expand_as(&output);
            output.addt_(1, &bias);
        }

        vec![output]
    }
    fn backward(&mut self, grad_output_list: &mut OptTensorKindList) -> OptTensorKindList {
        let tensorlist = self.saved_tensors();
        let grad_output_ = grad_output_list.remove(0);
        let needs_input_grad = self.needs_input_grad();
        let grad_output = match grad_output_ {
            Some(f) => f,
            None => unreachable!(),
        };
        let (input, weight) = (&tensorlist[0], &tensorlist[1]);
        let mut output: OptTensorKindList = Vec::new();
        let grad_input = if needs_input_grad[0] {
            Some(grad_output.mm(weight))
        } else {
            None
        };
        output.push(grad_input);
        let grad_weight = if needs_input_grad[1] {
            Some(grad_output.t().mm(input))
        } else {
            None
        };
        output.push(grad_weight);
        if tensorlist.len() > 0 && needs_input_grad[2] {
            let grad_bias = grad_output.sum_reduce(0, false);
            output.push(Some(grad_bias));
        }
        output
    }
}
<commit_msg>zero output first<commit_after>use autograd::{Function, FuncIntf, FuncDelegate, FIWrap};
use tensor::{OptTensorKindList, TensorKindList};

impl_func!(LinearF);

impl FuncIntf for LinearF {
    fn forward(&mut self, input_list: &mut TensorKindList) -> TensorKindList {
        self.save_for_backward(input_list);
        let (input, weight) = (input_list.remove(0), input_list.remove(0));
        let mut output = input.new((input.size()[0], weight.size()[0]));
        output.zero_().addmm_(0, 1, &input, &weight.t());
        if input_list.len() != 0 {
            let bias = input_list.remove(0).expand_as(&output);
            output.addt_(1, &bias);
        }
        vec![output]
    }
    fn backward(&mut self, grad_output_list: &mut OptTensorKindList) -> OptTensorKindList {
        let tensorlist = self.saved_tensors();
        let grad_output_ = grad_output_list.remove(0);
        let needs_input_grad = self.needs_input_grad();
        let grad_output = match grad_output_ {
            Some(f) => f,
            None => unreachable!(),
        };
        let (input, weight) = (&tensorlist[0], &tensorlist[1]);
        let mut output: OptTensorKindList = Vec::new();
        let grad_input = if needs_input_grad[0] {
            Some(grad_output.mm(weight))
        } else {
            None
        };
        output.push(grad_input);
        let grad_weight = if needs_input_grad[1] {
            Some(grad_output.t().mm(input))
        } else {
            None
        };
        output.push(grad_weight);
        if tensorlist.len() > 0 && needs_input_grad[2] {
            let grad_bias = grad_output.sum_reduce(0, false);
            output.push(Some(grad_bias));
        }
        output
    }
}
<|endoftext|>


<commit_before>use compression::{NUM_DOCS_PER_BLOCK, BlockDecoder, VIntDecoder};
use DocId;
use postings::{Postings, FreqHandler, DocSet, HasLen, SkipResult};
use std::cmp;
use fastfield::DeleteBitSet;

const EMPTY_DATA: [u8; 0] = [0u8; 0];

/// `SegmentPostings` represents the inverted list or postings associated to
/// a term in a `Segment`.
///
/// As we iterate through the `SegmentPostings`, the frequencies are optionally decoded.
/// Positions on the other hand, are optionally entirely decoded upfront.
pub struct SegmentPostings<'a> {
    block_cursor: BlockSegmentPostings<'a>,
    cur: usize,
    delete_bitset: DeleteBitSet,
}

impl<'a> SegmentPostings<'a> {

    /// Reads a Segment postings from an &[u8]
    ///
    /// * `len` - number of document in the posting lists.
    /// * `data` - data array. The complete data is not necessarily used.
    /// * `freq_handler` - the freq handler is in charge of decoding
    ///   frequencies and/or positions
    pub fn from_block_postings(
            segment_block_postings: BlockSegmentPostings<'a>,
            delete_bitset: DeleteBitSet) -> SegmentPostings<'a> {
        SegmentPostings {
            block_cursor: segment_block_postings,
            cur: NUM_DOCS_PER_BLOCK,  // cursor within the block
            delete_bitset: delete_bitset,
        }
    }

    /// Returns an empty segment postings object
    pub fn empty() -> SegmentPostings<'static> {
        let empty_block_cursor = BlockSegmentPostings::empty();
        SegmentPostings {
            block_cursor: empty_block_cursor,
            delete_bitset: DeleteBitSet::empty(),
            cur: NUM_DOCS_PER_BLOCK,
        }
    }
}

impl<'a> DocSet for SegmentPostings<'a> {
    // goes to the next element.
    // next needs to be called a first time to point to the correct element.
    #[inline]
    fn advance(&mut self) -> bool {
        loop {
            self.cur += 1;
            if self.cur >= self.block_cursor.block_len() {
                self.cur = 0;
                if !self.block_cursor.advance() {
                    self.cur = NUM_DOCS_PER_BLOCK;
                    return false;
                }
            }
            if !self.delete_bitset.is_deleted(self.doc()) {
                return true;
            }
        }
    }

    fn skip_next(&mut self, target: DocId) -> SkipResult {
        if !self.advance() {
            return SkipResult::End;
        }

        // skip blocks until one that might contain the target
        loop {
            // check if we need to go to the next block
            let (current_doc, last_doc_in_block) = {
                let block_docs = self.block_cursor.docs();
                (block_docs[self.cur], block_docs[block_docs.len() - 1])
            };
            if target > last_doc_in_block {
                if !self.block_cursor.advance() {
                    return SkipResult::End;
                }
                self.cur = 0;
            } else {
                if target < current_doc {
                    // We've overpassed the target after the first `advance` call
                    // or we're at the beginning of a block.
                    // Either way, we're on the first `DocId` greater than `target`
                    return SkipResult::OverStep;
                }
                break;
            }
        }
        {
            // we're in the right block now, start with an exponential search
            let block_docs = self.block_cursor.docs();
            let block_len = block_docs.len();

            debug_assert!(target >= block_docs[self.cur]);
            debug_assert!(target <= block_docs[block_len - 1]);

            let mut start = self.cur;
            let mut end = block_len;
            let mut count = 1;
            loop {
                let new = start + count;
                if new < end && block_docs[new] < target {
                    start = new;
                    count *= 2;
                } else {
                    break;
                }
            }
            end = cmp::min(start + count, end);

            // now do a binary search
            let mut count = end - start;
            while count > 0 {
                let step = count / 2;
                let mid = start + step;
                let doc = block_docs[mid];
                if doc < target {
                    start = mid + 1;
                    count -= step + 1;
                } else {
                    count = step;
                }
            }

            // `doc` is now >= `target`
            let doc = block_docs[start];
            self.cur = start;

            if !self.delete_bitset.is_deleted(doc) {
                if doc == target {
                    return SkipResult::Reached;
                } else {
                    return SkipResult::OverStep;
                }
            }
        }
        if self.advance() {
            SkipResult::OverStep
        } else {
            SkipResult::End
        }
    }

    #[inline]
    fn doc(&self) -> DocId {
        let docs = self.block_cursor.docs();
        assert!(self.cur < docs.len(), "Have you forgotten to call `.advance()` at least once before calling .doc().");
        docs[self.cur]
    }
}

impl<'a> HasLen for SegmentPostings<'a> {
    fn len(&self) -> usize {
        self.block_cursor.len
    }
}

impl<'a> Postings for SegmentPostings<'a> {
    fn term_freq(&self) -> u32 {
        self.block_cursor.freq_handler().freq(self.cur)
    }

    fn positions(&self) -> &[u32] {
        self.block_cursor.freq_handler().positions(self.cur)
    }
}

pub struct BlockSegmentPostings<'a> {
    block_decoder: BlockDecoder,
    len: usize,
    doc_offset: DocId,
    num_binpacked_blocks: usize,
    num_vint_docs: usize,
    remaining_data: &'a [u8],
    freq_handler: FreqHandler,
}

impl<'a> BlockSegmentPostings<'a> {

    pub fn from_data(len: usize, data: &'a [u8], freq_handler: FreqHandler) -> BlockSegmentPostings<'a> {
        let num_binpacked_blocks: usize = (len as usize) / NUM_DOCS_PER_BLOCK;
        let num_vint_docs = (len as usize) - NUM_DOCS_PER_BLOCK * num_binpacked_blocks;
        BlockSegmentPostings {
            num_binpacked_blocks: num_binpacked_blocks,
            num_vint_docs: num_vint_docs,
            block_decoder: BlockDecoder::new(),
            freq_handler: freq_handler,
            remaining_data: data,
            doc_offset: 0,
            len: len,
        }
    }

    pub fn reset(&mut self, len: usize, data: &'a [u8]) {
        let num_binpacked_blocks: usize = (len as usize) / NUM_DOCS_PER_BLOCK;
        let num_vint_docs = (len as usize) - NUM_DOCS_PER_BLOCK * num_binpacked_blocks;
        self.num_binpacked_blocks = num_binpacked_blocks;
        self.num_vint_docs = num_vint_docs;
        self.remaining_data = data;
        self.doc_offset = 0;
        self.len = len;
    }

    /// Returns the array of docs in the current block.
    #[inline]
    pub fn docs(&self) -> &[DocId] {
        self.block_decoder.output_array()
    }

    pub fn block_len(&self) -> usize {
        self.block_decoder.output_len
    }

    #[inline]
    pub fn freq_handler(&self) -> &FreqHandler {
        &self.freq_handler
    }

    pub fn advance(&mut self) -> bool {
        if self.num_binpacked_blocks > 0 {
            self.remaining_data = self.block_decoder.uncompress_block_sorted(self.remaining_data, self.doc_offset);
            self.remaining_data = self.freq_handler.read_freq_block(self.remaining_data);
            self.doc_offset = self.block_decoder.output(NUM_DOCS_PER_BLOCK - 1);
            self.num_binpacked_blocks -= 1;
            true
        }
        else {
            if self.num_vint_docs > 0 {
                self.remaining_data = self.block_decoder.uncompress_vint_sorted(self.remaining_data, self.doc_offset, self.num_vint_docs);
                self.freq_handler.read_freq_vint(self.remaining_data, self.num_vint_docs);
                self.num_vint_docs = 0;
                true
            }
            else {
                false
            }
        }
    }

    /// Returns an empty segment postings object
    pub fn empty() -> BlockSegmentPostings<'static> {
        BlockSegmentPostings {
            num_binpacked_blocks: 0,
            num_vint_docs: 0,
            block_decoder: BlockDecoder::new(),
            freq_handler: FreqHandler::new_without_freq(),
            remaining_data:  &EMPTY_DATA,
            doc_offset: 0,
            len: 0,
        }
    }

}

#[cfg(test)]
mod tests {

    use DocSet;
    use super::SegmentPostings;

    #[test]
    fn test_empty_segment_postings() {
        let mut postings = SegmentPostings::empty();
        assert!(!postings.advance());
        assert!(!postings.advance());
    }
}
<commit_msg>Inline block_len<commit_after>use compression::{NUM_DOCS_PER_BLOCK, BlockDecoder, VIntDecoder};
use DocId;
use postings::{Postings, FreqHandler, DocSet, HasLen, SkipResult};
use std::cmp;
use fastfield::DeleteBitSet;

const EMPTY_DATA: [u8; 0] = [0u8; 0];

/// `SegmentPostings` represents the inverted list or postings associated to
/// a term in a `Segment`.
///
/// As we iterate through the `SegmentPostings`, the frequencies are optionally decoded.
/// Positions on the other hand, are optionally entirely decoded upfront.
pub struct SegmentPostings<'a> {
    block_cursor: BlockSegmentPostings<'a>,
    cur: usize,
    delete_bitset: DeleteBitSet,
}

impl<'a> SegmentPostings<'a> {

    /// Reads a Segment postings from an &[u8]
    ///
    /// * `len` - number of document in the posting lists.
    /// * `data` - data array. The complete data is not necessarily used.
    /// * `freq_handler` - the freq handler is in charge of decoding
    ///   frequencies and/or positions
    pub fn from_block_postings(
            segment_block_postings: BlockSegmentPostings<'a>,
            delete_bitset: DeleteBitSet) -> SegmentPostings<'a> {
        SegmentPostings {
            block_cursor: segment_block_postings,
            cur: NUM_DOCS_PER_BLOCK,  // cursor within the block
            delete_bitset: delete_bitset,
        }
    }

    /// Returns an empty segment postings object
    pub fn empty() -> SegmentPostings<'static> {
        let empty_block_cursor = BlockSegmentPostings::empty();
        SegmentPostings {
            block_cursor: empty_block_cursor,
            delete_bitset: DeleteBitSet::empty(),
            cur: NUM_DOCS_PER_BLOCK,
        }
    }
}

impl<'a> DocSet for SegmentPostings<'a> {
    // goes to the next element.
    // next needs to be called a first time to point to the correct element.
    #[inline]
    fn advance(&mut self) -> bool {
        loop {
            self.cur += 1;
            if self.cur >= self.block_cursor.block_len() {
                self.cur = 0;
                if !self.block_cursor.advance() {
                    self.cur = NUM_DOCS_PER_BLOCK;
                    return false;
                }
            }
            if !self.delete_bitset.is_deleted(self.doc()) {
                return true;
            }
        }
    }

    fn skip_next(&mut self, target: DocId) -> SkipResult {
        if !self.advance() {
            return SkipResult::End;
        }

        // skip blocks until one that might contain the target
        loop {
            // check if we need to go to the next block
            let (current_doc, last_doc_in_block) = {
                let block_docs = self.block_cursor.docs();
                (block_docs[self.cur], block_docs[block_docs.len() - 1])
            };
            if target > last_doc_in_block {
                if !self.block_cursor.advance() {
                    return SkipResult::End;
                }
                self.cur = 0;
            } else {
                if target < current_doc {
                    // We've overpassed the target after the first `advance` call
                    // or we're at the beginning of a block.
                    // Either way, we're on the first `DocId` greater than `target`
                    return SkipResult::OverStep;
                }
                break;
            }
        }
        {
            // we're in the right block now, start with an exponential search
            let block_docs = self.block_cursor.docs();
            let block_len = block_docs.len();

            debug_assert!(target >= block_docs[self.cur]);
            debug_assert!(target <= block_docs[block_len - 1]);

            let mut start = self.cur;
            let mut end = block_len;
            let mut count = 1;
            loop {
                let new = start + count;
                if new < end && block_docs[new] < target {
                    start = new;
                    count *= 2;
                } else {
                    break;
                }
            }
            end = cmp::min(start + count, end);

            // now do a binary search
            let mut count = end - start;
            while count > 0 {
                let step = count / 2;
                let mid = start + step;
                let doc = block_docs[mid];
                if doc < target {
                    start = mid + 1;
                    count -= step + 1;
                } else {
                    count = step;
                }
            }

            // `doc` is now >= `target`
            let doc = block_docs[start];
            self.cur = start;

            if !self.delete_bitset.is_deleted(doc) {
                if doc == target {
                    return SkipResult::Reached;
                } else {
                    return SkipResult::OverStep;
                }
            }
        }
        if self.advance() {
            SkipResult::OverStep
        } else {
            SkipResult::End
        }
    }

    #[inline]
    fn doc(&self) -> DocId {
        let docs = self.block_cursor.docs();
        assert!(self.cur < docs.len(), "Have you forgotten to call `.advance()` at least once before calling .doc().");
        docs[self.cur]
    }
}

impl<'a> HasLen for SegmentPostings<'a> {
    fn len(&self) -> usize {
        self.block_cursor.len
    }
}

impl<'a> Postings for SegmentPostings<'a> {
    fn term_freq(&self) -> u32 {
        self.block_cursor.freq_handler().freq(self.cur)
    }

    fn positions(&self) -> &[u32] {
        self.block_cursor.freq_handler().positions(self.cur)
    }
}

pub struct BlockSegmentPostings<'a> {
    block_decoder: BlockDecoder,
    len: usize,
    doc_offset: DocId,
    num_binpacked_blocks: usize,
    num_vint_docs: usize,
    remaining_data: &'a [u8],
    freq_handler: FreqHandler,
}

impl<'a> BlockSegmentPostings<'a> {

    pub fn from_data(len: usize, data: &'a [u8], freq_handler: FreqHandler) -> BlockSegmentPostings<'a> {
        let num_binpacked_blocks: usize = (len as usize) / NUM_DOCS_PER_BLOCK;
        let num_vint_docs = (len as usize) - NUM_DOCS_PER_BLOCK * num_binpacked_blocks;
        BlockSegmentPostings {
            num_binpacked_blocks: num_binpacked_blocks,
            num_vint_docs: num_vint_docs,
            block_decoder: BlockDecoder::new(),
            freq_handler: freq_handler,
            remaining_data: data,
            doc_offset: 0,
            len: len,
        }
    }

    pub fn reset(&mut self, len: usize, data: &'a [u8]) {
        let num_binpacked_blocks: usize = (len as usize) / NUM_DOCS_PER_BLOCK;
        let num_vint_docs = (len as usize) - NUM_DOCS_PER_BLOCK * num_binpacked_blocks;
        self.num_binpacked_blocks = num_binpacked_blocks;
        self.num_vint_docs = num_vint_docs;
        self.remaining_data = data;
        self.doc_offset = 0;
        self.len = len;
    }

    /// Returns the array of docs in the current block.
    #[inline]
    pub fn docs(&self) -> &[DocId] {
        self.block_decoder.output_array()
    }

    #[inline]
    pub fn block_len(&self) -> usize {
        self.block_decoder.output_len
    }

    #[inline]
    pub fn freq_handler(&self) -> &FreqHandler {
        &self.freq_handler
    }

    pub fn advance(&mut self) -> bool {
        if self.num_binpacked_blocks > 0 {
            self.remaining_data = self.block_decoder.uncompress_block_sorted(self.remaining_data, self.doc_offset);
            self.remaining_data = self.freq_handler.read_freq_block(self.remaining_data);
            self.doc_offset = self.block_decoder.output(NUM_DOCS_PER_BLOCK - 1);
            self.num_binpacked_blocks -= 1;
            true
        }
        else {
            if self.num_vint_docs > 0 {
                self.remaining_data = self.block_decoder.uncompress_vint_sorted(self.remaining_data, self.doc_offset, self.num_vint_docs);
                self.freq_handler.read_freq_vint(self.remaining_data, self.num_vint_docs);
                self.num_vint_docs = 0;
                true
            }
            else {
                false
            }
        }
    }

    /// Returns an empty segment postings object
    pub fn empty() -> BlockSegmentPostings<'static> {
        BlockSegmentPostings {
            num_binpacked_blocks: 0,
            num_vint_docs: 0,
            block_decoder: BlockDecoder::new(),
            freq_handler: FreqHandler::new_without_freq(),
            remaining_data:  &EMPTY_DATA,
            doc_offset: 0,
            len: 0,
        }
    }

}

#[cfg(test)]
mod tests {

    use DocSet;
    use super::SegmentPostings;

    #[test]
    fn test_empty_segment_postings() {
        let mut postings = SegmentPostings::empty();
        assert!(!postings.advance());
        assert!(!postings.advance());
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate diesel;

use diesel::*;
use diesel::dsl::count_star;

table! {
    users {
        id -> Integer,
    }
}

fn main() {
    use self::users::dsl::*;

    let source = users.select((id, count_star()));
    //~^ ERROR MixedAggregates
}
<commit_msg>Add a few more compile fail tests for mixed selects<commit_after>#[macro_use]
extern crate diesel;

use diesel::dsl::count_star;
use diesel::sql_types::{Integer, Nullable};
use diesel::*;

table! {
    users {
        id -> Integer,
        nullable_int_col -> Nullable<Integer>,
    }
}

sql_function!(fn f(x: Nullable<Integer>, y: Nullable<Integer>) -> Nullable<Integer>);

fn main() {
    use self::users::dsl::*;
    use diesel::dsl::max;

    let source = users.select((id, count_star()));
    //~^ ERROR MixedAggregates

    let source = users.select(nullable_int_col + max(nullable_int_col));
    //~^ ERROR MixedAggregates

    let source = users.select(f(nullable_int_col, max(nullable_int_col)));
    //~^ ERROR MixedAggregates
}
<|endoftext|>


<commit_before>use LalafellBot;
use tasks::{RunsTask, FromConfig};
use config::Task;
use discord::GetMessages;
use discord::model::ChannelId;
use chrono::prelude::*;
use chrono::Duration;

use xivdb::error::*;
use serde_json;

use std::sync::Arc;
use std::thread;

#[derive(Debug)]
pub struct DeleteAllMessagesTask {
  config: DeleteAllMessagesTaskConfig,
  next_sleep: i64
}

impl RunsTask for DeleteAllMessagesTask {
  fn start(mut self, s: Arc<LalafellBot>) {
    loop {
      thread::sleep(Duration::seconds(self.next_sleep).to_std().unwrap());
      info!("Delete messages task running");
      let channel = ChannelId(self.config.channel);
      let messages = match s.discord.get_messages(channel, GetMessages::MostRecent, None) {
        Ok(m) => m,
        Err(e) => {
          warn!("Could not get messages for channel {}: {}", channel, e);
          self.next_sleep = 30;
          continue;
        }
      };
      for message in messages {
        if self.config.except.contains(&message.id.0) {
          continue;
        }
        let timestamp: DateTime<UTC> = match message.timestamp.parse() {
          Ok(t) => t,
          Err(e) => {
            warn!("Could not parse message timestamp: {}", e);
            continue;
          }
        };
        if timestamp + Duration::seconds(self.config.after) > UTC::now() {
          continue;
        }
        if let Err(e) = s.discord.delete_message(message.channel_id, message.id) {
          warn!("Could not delete message {}: {}", message.id, e);
        }
      }
      self.next_sleep = 60;
      info!("Delete messages task done");
    }
  }
}

impl FromConfig for DeleteAllMessagesTask {
  fn from_config(task: &Task) -> Result<Self> {
    let val = match task.config {
      None => return Err("delete_all_messages task is missing configuration".into()),
      Some(ref val) => val
    };
    let config: DeleteAllMessagesTaskConfig = serde_json::from_value(val.clone()).chain_err(|| "could not parse delete_all_messages configuration")?;
    Ok(DeleteAllMessagesTask {
      config: config,
      next_sleep: Default::default()
    })
  }
}

#[derive(Debug, Deserialize)]
pub struct DeleteAllMessagesTaskConfig {
  pub channel: u64,
  pub after: i64,
  pub except: Vec<u64>
}
<commit_msg>fix: allow except field to be empty<commit_after>use LalafellBot;
use tasks::{RunsTask, FromConfig};
use config::Task;
use discord::GetMessages;
use discord::model::ChannelId;
use chrono::prelude::*;
use chrono::Duration;

use xivdb::error::*;
use serde_json;

use std::sync::Arc;
use std::thread;

#[derive(Debug)]
pub struct DeleteAllMessagesTask {
  config: DeleteAllMessagesTaskConfig,
  next_sleep: i64
}

impl RunsTask for DeleteAllMessagesTask {
  fn start(mut self, s: Arc<LalafellBot>) {
    loop {
      thread::sleep(Duration::seconds(self.next_sleep).to_std().unwrap());
      info!("Delete messages task running");
      let channel = ChannelId(self.config.channel);
      let messages = match s.discord.get_messages(channel, GetMessages::MostRecent, None) {
        Ok(m) => m,
        Err(e) => {
          warn!("Could not get messages for channel {}: {}", channel, e);
          self.next_sleep = 30;
          continue;
        }
      };
      for message in messages {
        if self.config.except.contains(&message.id.0) {
          continue;
        }
        let timestamp: DateTime<UTC> = match message.timestamp.parse() {
          Ok(t) => t,
          Err(e) => {
            warn!("Could not parse message timestamp: {}", e);
            continue;
          }
        };
        if timestamp + Duration::seconds(self.config.after) > UTC::now() {
          continue;
        }
        if let Err(e) = s.discord.delete_message(message.channel_id, message.id) {
          warn!("Could not delete message {}: {}", message.id, e);
        }
      }
      self.next_sleep = 60;
      info!("Delete messages task done");
    }
  }
}

impl FromConfig for DeleteAllMessagesTask {
  fn from_config(task: &Task) -> Result<Self> {
    let val = match task.config {
      None => return Err("delete_all_messages task is missing configuration".into()),
      Some(ref val) => val
    };
    let config: DeleteAllMessagesTaskConfig = serde_json::from_value(val.clone()).chain_err(|| "could not parse delete_all_messages configuration")?;
    Ok(DeleteAllMessagesTask {
      config: config,
      next_sleep: Default::default()
    })
  }
}

#[derive(Debug, Deserialize)]
pub struct DeleteAllMessagesTaskConfig {
  pub channel: u64,
  pub after: i64,
  #[serde(default)]
  pub except: Vec<u64>
}
<|endoftext|>


<commit_before>// Copyright 2014 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.

use std::os;

static PI: f64 = 3.141592653589793;
static SOLAR_MASS: f64 = 4.0 * PI * PI;
static YEAR: f64 = 365.24;
static N_BODIES: uint = 5;

static BODIES: [Planet, ..N_BODIES] = [
    // Sun
    Planet {
        x: [ 0.0, 0.0, 0.0 ],
        v: [ 0.0, 0.0, 0.0 ],
        mass: SOLAR_MASS,
    },
    // Jupiter
    Planet {
        x: [
            4.84143144246472090e+00,
            -1.16032004402742839e+00,
            -1.03622044471123109e-01,
        ],
        v: [
            1.66007664274403694e-03 * YEAR,
            7.69901118419740425e-03 * YEAR,
            -6.90460016972063023e-05 * YEAR,
        ],
        mass: 9.54791938424326609e-04 * SOLAR_MASS,
    },
    // Saturn
    Planet {
        x: [
            8.34336671824457987e+00,
            4.12479856412430479e+00,
            -4.03523417114321381e-01,
        ],
        v: [
            -2.76742510726862411e-03 * YEAR,
            4.99852801234917238e-03 * YEAR,
            2.30417297573763929e-05 * YEAR,
        ],
        mass: 2.85885980666130812e-04 * SOLAR_MASS,
    },
    // Uranus
    Planet {
        x: [
            1.28943695621391310e+01,
            -1.51111514016986312e+01,
            -2.23307578892655734e-01,
        ],
        v: [
            2.96460137564761618e-03 * YEAR,
            2.37847173959480950e-03 * YEAR,
            -2.96589568540237556e-05 * YEAR,
        ],
        mass: 4.36624404335156298e-05 * SOLAR_MASS,
    },
    // Neptune
    Planet {
        x: [
            1.53796971148509165e+01,
            -2.59193146099879641e+01,
            1.79258772950371181e-01,
        ],
        v: [
            2.68067772490389322e-03 * YEAR,
            1.62824170038242295e-03 * YEAR,
            -9.51592254519715870e-05 * YEAR,
        ],
        mass: 5.15138902046611451e-05 * SOLAR_MASS,
    },
];

struct Planet {
    x: [f64, ..3],
    v: [f64, ..3],
    mass: f64,
}

fn advance(bodies: &mut [Planet, ..N_BODIES], dt: f64, steps: i32) {
    let mut d = [ 0.0, ..3 ];
    for _ in range(0, steps) {
        for i in range(0u, N_BODIES) {
            for j in range(i + 1, N_BODIES) {
                d[0] = bodies[i].x[0] - bodies[j].x[0];
                d[1] = bodies[i].x[1] - bodies[j].x[1];
                d[2] = bodies[i].x[2] - bodies[j].x[2];

                let d2 = d[0]*d[0] + d[1]*d[1] + d[2]*d[2];
                let mag = dt / (d2 * d2.sqrt());

                let a_mass = bodies[i].mass;
                let b_mass = bodies[j].mass;
                bodies[i].v[0] -= d[0] * b_mass * mag;
                bodies[i].v[1] -= d[1] * b_mass * mag;
                bodies[i].v[2] -= d[2] * b_mass * mag;

                bodies[j].v[0] += d[0] * a_mass * mag;
                bodies[j].v[1] += d[1] * a_mass * mag;
                bodies[j].v[2] += d[2] * a_mass * mag;
            }
        }

        for a in bodies.mut_iter() {
            a.x[0] += dt * a.v[0];
            a.x[1] += dt * a.v[1];
            a.x[2] += dt * a.v[2];
        }
    }
}

fn energy(bodies: &[Planet, ..N_BODIES]) -> f64 {
    let mut e = 0.0;
    let mut d = [ 0.0, ..3 ];
    for i in range(0u, N_BODIES) {
        for k in range(0u, 3) {
            e += bodies[i].mass * bodies[i].v[k] * bodies[i].v[k] / 2.0;
        }

        for j in range(i + 1, N_BODIES) {
            for k in range(0u, 3) {
                d[k] = bodies[i].x[k] - bodies[j].x[k];
            }
            let dist = (d[0]*d[0] + d[1]*d[1] + d[2]*d[2]).sqrt();
            e -= bodies[i].mass * bodies[j].mass / dist;
        }
    }
    e
}

fn offset_momentum(bodies: &mut [Planet, ..N_BODIES]) {
    for i in range(0u, N_BODIES) {
        for k in range(0u, 3) {
            bodies[0].v[k] -= bodies[i].v[k] * bodies[i].mass / SOLAR_MASS;
        }
    }
}

fn main() {
    let args = os::args();
    let args = if os::getenv("RUST_BENCH").is_some() {
        vec!("".to_owned(), "1000".to_owned())
    } else if args.len() <= 1u {
        vec!("".to_owned(), "1000".to_owned())
    } else {
        args.move_iter().collect()
    };

    let n: i32 = from_str::<i32>(*args.get(1)).unwrap();
    let mut bodies = BODIES;

    offset_momentum(&mut bodies);
    println!("{:.9f}", energy(&bodies) as f64);

    advance(&mut bodies, 0.01, n);

    println!("{:.9f}", energy(&bodies) as f64);
}

<commit_msg>shootout-nbody improvements<commit_after>// Copyright 2014 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.

static PI: f64 = 3.141592653589793;
static SOLAR_MASS: f64 = 4.0 * PI * PI;
static YEAR: f64 = 365.24;
static N_BODIES: uint = 5;

static BODIES: [Planet, ..N_BODIES] = [
    // Sun
    Planet {
        x: 0.0, y: 0.0, z: 0.0,
        vx: 0.0, vy: 0.0, vz: 0.0,
        mass: SOLAR_MASS,
    },
    // Jupiter
    Planet {
        x: 4.84143144246472090e+00,
        y: -1.16032004402742839e+00,
        z: -1.03622044471123109e-01,
        vx: 1.66007664274403694e-03 * YEAR,
        vy: 7.69901118419740425e-03 * YEAR,
        vz: -6.90460016972063023e-05 * YEAR,
        mass: 9.54791938424326609e-04 * SOLAR_MASS,
    },
    // Saturn
    Planet {
        x: 8.34336671824457987e+00,
        y: 4.12479856412430479e+00,
        z: -4.03523417114321381e-01,
        vx: -2.76742510726862411e-03 * YEAR,
        vy: 4.99852801234917238e-03 * YEAR,
        vz: 2.30417297573763929e-05 * YEAR,
        mass: 2.85885980666130812e-04 * SOLAR_MASS,
    },
    // Uranus
    Planet {
        x: 1.28943695621391310e+01,
        y: -1.51111514016986312e+01,
        z: -2.23307578892655734e-01,
        vx: 2.96460137564761618e-03 * YEAR,
        vy: 2.37847173959480950e-03 * YEAR,
        vz: -2.96589568540237556e-05 * YEAR,
        mass: 4.36624404335156298e-05 * SOLAR_MASS,
    },
    // Neptune
    Planet {
        x: 1.53796971148509165e+01,
        y: -2.59193146099879641e+01,
        z: 1.79258772950371181e-01,
        vx: 2.68067772490389322e-03 * YEAR,
        vy: 1.62824170038242295e-03 * YEAR,
        vz: -9.51592254519715870e-05 * YEAR,
        mass: 5.15138902046611451e-05 * SOLAR_MASS,
    },
];

struct Planet {
    x: f64, y: f64, z: f64,
    vx: f64, vy: f64, vz: f64,
    mass: f64,
}

fn advance(bodies: &mut [Planet, ..N_BODIES], dt: f64, steps: int) {
    for _ in range(0, steps) {
        {
            let mut b_slice = bodies.as_mut_slice();
            loop {
                let bi = match b_slice.mut_shift_ref() {
                    Some(bi) => bi,
                    None => break
                };
                for bj in b_slice.mut_iter() {
                    let dx = bi.x - bj.x;
                    let dy = bi.y - bj.y;
                    let dz = bi.z - bj.z;

                    let d2 = dx * dx + dy * dy + dz * dz;
                    let mag = dt / (d2 * d2.sqrt());

                    bi.vx -= dx * bj.mass * mag;
                    bi.vy -= dy * bj.mass * mag;
                    bi.vz -= dz * bj.mass * mag;

                    bj.vx += dx * bi.mass * mag;
                    bj.vy += dy * bi.mass * mag;
                    bj.vz += dz * bi.mass * mag;
                }
            }
        }

        for bi in bodies.mut_iter() {
            bi.x += dt * bi.vx;
            bi.y += dt * bi.vy;
            bi.z += dt * bi.vz;
        }
    }
}

fn energy(bodies: &[Planet, ..N_BODIES]) -> f64 {
    let mut e = 0.0;
    let mut bodies = bodies.as_slice();
    loop {
        let bi = match bodies.shift_ref() {
            Some(bi) => bi,
            None => break
        };
        e += (bi.vx * bi.vx + bi.vy * bi.vy + bi.vz * bi.vz) * bi.mass / 2.0;
        for bj in bodies.iter() {
            let dx = bi.x - bj.x;
            let dy = bi.y - bj.y;
            let dz = bi.z - bj.z;
            let dist = (dx * dx + dy * dy + dz * dz).sqrt();
            e -= bi.mass * bj.mass / dist;
        }
    }
    e
}

fn offset_momentum(bodies: &mut [Planet, ..N_BODIES]) {
    let mut px = 0.0;
    let mut py = 0.0;
    let mut pz = 0.0;
    for bi in bodies.iter() {
        px += bi.vx * bi.mass;
        py += bi.vy * bi.mass;
        pz += bi.vz * bi.mass;
    }
    let sun = &mut bodies[0];
    sun.vx = - px / SOLAR_MASS;
    sun.vy = - py / SOLAR_MASS;
    sun.vz = - pz / SOLAR_MASS;
}

fn main() {
    let n = if std::os::getenv("RUST_BENCH").is_some() {
        5000000
    } else {
        std::os::args().as_slice().get(1)
            .and_then(|arg| from_str(*arg))
            .unwrap_or(1000)
    };
    let mut bodies = BODIES;

    offset_momentum(&mut bodies);
    println!("{:.9f}", energy(&bodies));

    advance(&mut bodies, 0.01, n);

    println!("{:.9f}", energy(&bodies));
}
<|endoftext|>


<commit_before>//! Workspace information we get from cargo consists of two pieces. The first is
//! the output of `cargo metadata`. The second is the output of running
//! `build.rs` files (`OUT_DIR` env var, extra cfg flags) and compiling proc
//! macro.
//!
//! This module implements this second part. We use "build script" terminology
//! here, but it covers procedural macros as well.

use std::{cell::RefCell, io, path::PathBuf, process::Command};

use cargo_metadata::{camino::Utf8Path, Message};
use la_arena::ArenaMap;
use paths::AbsPathBuf;
use rustc_hash::FxHashMap;
use semver::Version;
use serde::Deserialize;

use crate::{cfg_flag::CfgFlag, CargoConfig, CargoWorkspace, Package};

#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct WorkspaceBuildScripts {
    outputs: ArenaMap<Package, Option<BuildScriptOutput>>,
    error: Option<String>,
}

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub(crate) struct BuildScriptOutput {
    /// List of config flags defined by this package's build script.
    pub(crate) cfgs: Vec<CfgFlag>,
    /// List of cargo-related environment variables with their value.
    ///
    /// If the package has a build script which defines environment variables,
    /// they can also be found here.
    pub(crate) envs: Vec<(String, String)>,
    /// Directory where a build script might place its output.
    pub(crate) out_dir: Option<AbsPathBuf>,
    /// Path to the proc-macro library file if this package exposes proc-macros.
    pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>,
}

impl WorkspaceBuildScripts {
    fn build_command(config: &CargoConfig, toolchain: &Option<Version>) -> Command {
        if let Some([program, args @ ..]) = config.run_build_script_command.as_deref() {
            let mut cmd = Command::new(program);
            cmd.args(args);
            return cmd;
        }

        let mut cmd = Command::new(toolchain::cargo());

        cmd.args(&["check", "--quiet", "--workspace", "--message-format=json"]);

        // --all-targets includes tests, benches and examples in addition to the
        // default lib and bins. This is an independent concept from the --targets
        // flag below.
        cmd.arg("--all-targets");

        if let Some(target) = &config.target {
            cmd.args(&["--target", target]);
        }

        if config.all_features {
            cmd.arg("--all-features");
        } else {
            if config.no_default_features {
                cmd.arg("--no-default-features");
            }
            if !config.features.is_empty() {
                cmd.arg("--features");
                cmd.arg(config.features.join(" "));
            }
        }

        const RUST_1_62: Version = Version::new(1, 62, 0);

        match toolchain {
            Some(v) if v >= &RUST_1_62 => {
                cmd.args(&["-Z", "unstable-options", "--keep-going"]).env("RUSTC_BOOTSTRAP", "1");
            }
            _ => (),
        }

        cmd
    }

    pub(crate) fn run(
        config: &CargoConfig,
        workspace: &CargoWorkspace,
        progress: &dyn Fn(String),
        toolchain: &Option<Version>,
    ) -> io::Result<WorkspaceBuildScripts> {
        let mut cmd = Self::build_command(config, toolchain);

        if config.wrap_rustc_in_build_scripts {
            // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use
            // that to compile only proc macros and build scripts during the initial
            // `cargo check`.
            let myself = std::env::current_exe()?;
            cmd.env("RUSTC_WRAPPER", myself);
            cmd.env("RA_RUSTC_WRAPPER", "1");
        }

        cmd.current_dir(workspace.workspace_root());

        let mut res = WorkspaceBuildScripts::default();
        let outputs = &mut res.outputs;
        // NB: Cargo.toml could have been modified between `cargo metadata` and
        // `cargo check`. We shouldn't assume that package ids we see here are
        // exactly those from `config`.
        let mut by_id: FxHashMap<String, Package> = FxHashMap::default();
        for package in workspace.packages() {
            outputs.insert(package, None);
            by_id.insert(workspace[package].id.clone(), package);
        }

        let errors = RefCell::new(String::new());
        let push_err = |err: &str| {
            let mut e = errors.borrow_mut();
            e.push_str(err);
            e.push('\n');
        };

        tracing::info!("Running build scripts: {:?}", cmd);
        let output = stdx::process::spawn_with_streaming_output(
            cmd,
            &mut |line| {
                // Copy-pasted from existing cargo_metadata. It seems like we
                // should be using serde_stacker here?
                let mut deserializer = serde_json::Deserializer::from_str(line);
                deserializer.disable_recursion_limit();
                let message = Message::deserialize(&mut deserializer)
                    .unwrap_or_else(|_| Message::TextLine(line.to_string()));

                match message {
                    Message::BuildScriptExecuted(message) => {
                        let package = match by_id.get(&message.package_id.repr) {
                            Some(&it) => it,
                            None => return,
                        };
                        let cfgs = {
                            let mut acc = Vec::new();
                            for cfg in message.cfgs {
                                match cfg.parse::<CfgFlag>() {
                                    Ok(it) => acc.push(it),
                                    Err(err) => {
                                        push_err(&format!(
                                            "invalid cfg from cargo-metadata: {}",
                                            err
                                        ));
                                        return;
                                    }
                                };
                            }
                            acc
                        };
                        // cargo_metadata crate returns default (empty) path for
                        // older cargos, which is not absolute, so work around that.
                        let out_dir = message.out_dir.into_os_string();
                        if !out_dir.is_empty() {
                            let data = outputs[package].get_or_insert_with(Default::default);
                            data.out_dir = Some(AbsPathBuf::assert(PathBuf::from(out_dir)));
                            data.cfgs = cfgs;
                        }
                        if !message.env.is_empty() {
                            outputs[package].get_or_insert_with(Default::default).envs =
                                message.env;
                        }
                    }
                    Message::CompilerArtifact(message) => {
                        let package = match by_id.get(&message.package_id.repr) {
                            Some(it) => *it,
                            None => return,
                        };

                        progress(format!("metadata {}", message.target.name));

                        if message.target.kind.iter().any(|k| k == "proc-macro") {
                            // Skip rmeta file
                            if let Some(filename) =
                                message.filenames.iter().find(|name| is_dylib(name))
                            {
                                let filename = AbsPathBuf::assert(PathBuf::from(&filename));
                                outputs[package]
                                    .get_or_insert_with(Default::default)
                                    .proc_macro_dylib_path = Some(filename);
                            }
                        }
                    }
                    Message::CompilerMessage(message) => {
                        progress(message.target.name);

                        if let Some(diag) = message.message.rendered.as_deref() {
                            push_err(diag);
                        }
                    }
                    Message::BuildFinished(_) => {}
                    Message::TextLine(_) => {}
                    _ => {}
                }
            },
            &mut |line| {
                push_err(line);
            },
        )?;

        for package in workspace.packages() {
            if let Some(package_build_data) = &mut outputs[package] {
                tracing::info!(
                    "{}: {:?}",
                    workspace[package].manifest.parent().display(),
                    package_build_data,
                );
                // inject_cargo_env(package, package_build_data);
                if let Some(out_dir) = &package_build_data.out_dir {
                    // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!()
                    if let Some(out_dir) = out_dir.as_os_str().to_str().map(|s| s.to_owned()) {
                        package_build_data.envs.push(("OUT_DIR".to_string(), out_dir));
                    }
                }
            }
        }

        let mut errors = errors.into_inner();
        if !output.status.success() {
            if errors.is_empty() {
                errors = "cargo check failed".to_string();
            }
            res.error = Some(errors);
        }

        Ok(res)
    }

    pub fn error(&self) -> Option<&str> {
        self.error.as_deref()
    }

    pub(crate) fn get_output(&self, idx: Package) -> Option<&BuildScriptOutput> {
        self.outputs.get(idx)?.as_ref()
    }
}

// FIXME: File a better way to know if it is a dylib.
fn is_dylib(path: &Utf8Path) -> bool {
    match path.extension().map(|e| e.to_string().to_lowercase()) {
        None => false,
        Some(ext) => matches!(ext.as_str(), "dll" | "dylib" | "so"),
    }
}
<commit_msg>Re-try build script building with --keep-going<commit_after>//! Workspace information we get from cargo consists of two pieces. The first is
//! the output of `cargo metadata`. The second is the output of running
//! `build.rs` files (`OUT_DIR` env var, extra cfg flags) and compiling proc
//! macro.
//!
//! This module implements this second part. We use "build script" terminology
//! here, but it covers procedural macros as well.

use std::{cell::RefCell, io, path::PathBuf, process::Command};

use cargo_metadata::{camino::Utf8Path, Message};
use la_arena::ArenaMap;
use paths::AbsPathBuf;
use rustc_hash::FxHashMap;
use semver::Version;
use serde::Deserialize;

use crate::{cfg_flag::CfgFlag, CargoConfig, CargoWorkspace, Package};

#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct WorkspaceBuildScripts {
    outputs: ArenaMap<Package, Option<BuildScriptOutput>>,
    error: Option<String>,
}

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub(crate) struct BuildScriptOutput {
    /// List of config flags defined by this package's build script.
    pub(crate) cfgs: Vec<CfgFlag>,
    /// List of cargo-related environment variables with their value.
    ///
    /// If the package has a build script which defines environment variables,
    /// they can also be found here.
    pub(crate) envs: Vec<(String, String)>,
    /// Directory where a build script might place its output.
    pub(crate) out_dir: Option<AbsPathBuf>,
    /// Path to the proc-macro library file if this package exposes proc-macros.
    pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>,
}

impl WorkspaceBuildScripts {
    fn build_command(config: &CargoConfig) -> Command {
        if let Some([program, args @ ..]) = config.run_build_script_command.as_deref() {
            let mut cmd = Command::new(program);
            cmd.args(args);
            return cmd;
        }

        let mut cmd = Command::new(toolchain::cargo());

        cmd.args(&["check", "--quiet", "--workspace", "--message-format=json"]);

        // --all-targets includes tests, benches and examples in addition to the
        // default lib and bins. This is an independent concept from the --targets
        // flag below.
        cmd.arg("--all-targets");

        if let Some(target) = &config.target {
            cmd.args(&["--target", target]);
        }

        if config.all_features {
            cmd.arg("--all-features");
        } else {
            if config.no_default_features {
                cmd.arg("--no-default-features");
            }
            if !config.features.is_empty() {
                cmd.arg("--features");
                cmd.arg(config.features.join(" "));
            }
        }

        cmd
    }

    pub(crate) fn run(
        config: &CargoConfig,
        workspace: &CargoWorkspace,
        progress: &dyn Fn(String),
        toolchain: &Option<Version>,
    ) -> io::Result<WorkspaceBuildScripts> {
        const RUST_1_62: Version = Version::new(1, 62, 0);

        match Self::run_(Self::build_command(config), config, workspace, progress) {
            Ok(WorkspaceBuildScripts { error: Some(error), .. })
                if toolchain.as_ref().map_or(false, |it| *it >= RUST_1_62) =>
            {
                // building build scripts failed, attempt to build with --keep-going so
                // that we potentially get more build data
                let mut cmd = Self::build_command(config);
                cmd.args(&["-Z", "unstable-options", "--keep-going"]).env("RUSTC_BOOTSTRAP", "1");
                let mut res = Self::run_(cmd, config, workspace, progress)?;
                res.error = Some(error);
                Ok(res)
            }
            res => res,
        }
    }

    fn run_(
        mut cmd: Command,
        config: &CargoConfig,
        workspace: &CargoWorkspace,
        progress: &dyn Fn(String),
    ) -> io::Result<WorkspaceBuildScripts> {
        if config.wrap_rustc_in_build_scripts {
            // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use
            // that to compile only proc macros and build scripts during the initial
            // `cargo check`.
            let myself = std::env::current_exe()?;
            cmd.env("RUSTC_WRAPPER", myself);
            cmd.env("RA_RUSTC_WRAPPER", "1");
        }

        cmd.current_dir(workspace.workspace_root());

        let mut res = WorkspaceBuildScripts::default();
        let outputs = &mut res.outputs;
        // NB: Cargo.toml could have been modified between `cargo metadata` and
        // `cargo check`. We shouldn't assume that package ids we see here are
        // exactly those from `config`.
        let mut by_id: FxHashMap<String, Package> = FxHashMap::default();
        for package in workspace.packages() {
            outputs.insert(package, None);
            by_id.insert(workspace[package].id.clone(), package);
        }

        let errors = RefCell::new(String::new());
        let push_err = |err: &str| {
            let mut e = errors.borrow_mut();
            e.push_str(err);
            e.push('\n');
        };

        tracing::info!("Running build scripts: {:?}", cmd);
        let output = stdx::process::spawn_with_streaming_output(
            cmd,
            &mut |line| {
                // Copy-pasted from existing cargo_metadata. It seems like we
                // should be using serde_stacker here?
                let mut deserializer = serde_json::Deserializer::from_str(line);
                deserializer.disable_recursion_limit();
                let message = Message::deserialize(&mut deserializer)
                    .unwrap_or_else(|_| Message::TextLine(line.to_string()));

                match message {
                    Message::BuildScriptExecuted(message) => {
                        let package = match by_id.get(&message.package_id.repr) {
                            Some(&it) => it,
                            None => return,
                        };
                        let cfgs = {
                            let mut acc = Vec::new();
                            for cfg in message.cfgs {
                                match cfg.parse::<CfgFlag>() {
                                    Ok(it) => acc.push(it),
                                    Err(err) => {
                                        push_err(&format!(
                                            "invalid cfg from cargo-metadata: {}",
                                            err
                                        ));
                                        return;
                                    }
                                };
                            }
                            acc
                        };
                        // cargo_metadata crate returns default (empty) path for
                        // older cargos, which is not absolute, so work around that.
                        let out_dir = message.out_dir.into_os_string();
                        if !out_dir.is_empty() {
                            let data = outputs[package].get_or_insert_with(Default::default);
                            data.out_dir = Some(AbsPathBuf::assert(PathBuf::from(out_dir)));
                            data.cfgs = cfgs;
                        }
                        if !message.env.is_empty() {
                            outputs[package].get_or_insert_with(Default::default).envs =
                                message.env;
                        }
                    }
                    Message::CompilerArtifact(message) => {
                        let package = match by_id.get(&message.package_id.repr) {
                            Some(it) => *it,
                            None => return,
                        };

                        progress(format!("metadata {}", message.target.name));

                        if message.target.kind.iter().any(|k| k == "proc-macro") {
                            // Skip rmeta file
                            if let Some(filename) =
                                message.filenames.iter().find(|name| is_dylib(name))
                            {
                                let filename = AbsPathBuf::assert(PathBuf::from(&filename));
                                outputs[package]
                                    .get_or_insert_with(Default::default)
                                    .proc_macro_dylib_path = Some(filename);
                            }
                        }
                    }
                    Message::CompilerMessage(message) => {
                        progress(message.target.name);

                        if let Some(diag) = message.message.rendered.as_deref() {
                            push_err(diag);
                        }
                    }
                    Message::BuildFinished(_) => {}
                    Message::TextLine(_) => {}
                    _ => {}
                }
            },
            &mut |line| {
                push_err(line);
            },
        )?;

        for package in workspace.packages() {
            if let Some(package_build_data) = &mut outputs[package] {
                tracing::info!(
                    "{}: {:?}",
                    workspace[package].manifest.parent().display(),
                    package_build_data,
                );
                // inject_cargo_env(package, package_build_data);
                if let Some(out_dir) = &package_build_data.out_dir {
                    // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!()
                    if let Some(out_dir) = out_dir.as_os_str().to_str().map(|s| s.to_owned()) {
                        package_build_data.envs.push(("OUT_DIR".to_string(), out_dir));
                    }
                }
            }
        }

        let mut errors = errors.into_inner();
        if !output.status.success() {
            if errors.is_empty() {
                errors = "cargo check failed".to_string();
            }
            res.error = Some(errors);
        }

        Ok(res)
    }

    pub fn error(&self) -> Option<&str> {
        self.error.as_deref()
    }

    pub(crate) fn get_output(&self, idx: Package) -> Option<&BuildScriptOutput> {
        self.outputs.get(idx)?.as_ref()
    }
}

// FIXME: File a better way to know if it is a dylib.
fn is_dylib(path: &Utf8Path) -> bool {
    match path.extension().map(|e| e.to_string().to_lowercase()) {
        None => false,
        Some(ext) => matches!(ext.as_str(), "dll" | "dylib" | "so"),
    }
}
<|endoftext|>