<commit_before>use std::collections::HashMap;
use std::fs;
use std::path::*;
use std::io::{Result, Write};
use case::CaseExt;

use analysis::rust_type::parameter_rust_type;
use env::Env;
use file_saver::*;
use library;
use nameutil::*;
use super::ffi_type::ffi_type;
use super::functions;
use super::statics;
use super::super::general::{self, tabs};
use traits::*;

pub fn generate(env: &Env) {
    println!("generating sys for {}", env.config.library_name);

    let path =  PathBuf::from(&env.config.target_path)
        .join(file_name_sys("lib"));

    let parent = path.parent().unwrap();
    //TODO: do only if not exists
    let _ = fs::create_dir(parent);

    println!("Generating file {:?}", path);
    save_to_file(&path, &mut |w| generate_lib(w, env));
}

fn generate_lib<W: Write>(w: &mut W, env: &Env) -> Result<()>{
    try!(general::start_comments(w, &env.config));
    try!(statics::begin(w));

    try!(generate_extern_crates(w, env));
    try!(statics::after_extern_crates(w));

    if env.config.library_name != "GLib" {
        try!(statics::use_glib_ffi(w));
    } else {
        try!(statics::only_for_glib(w));
    }
    if env.config.library_name == "Gtk" {
        try!(statics::only_for_gtk(w));
    }

    let ns = env.library.namespace(library::MAIN_NAMESPACE);
    let records = prepare(ns);
    let classes = prepare(ns);
    let interfaces = prepare(ns);

    try!(generate_aliases(w, env, &prepare(ns)));
    try!(generate_enums(w, &prepare(ns)));
    try!(generate_constants(w, env, &ns.constants));
    try!(generate_bitfields(w, &prepare(ns)));
    try!(generate_unions(w, &prepare(ns)));
    try!(functions::generate_callbacks(w, env, &prepare(ns)));
    try!(generate_records(w, env, &records));
    try!(generate_classes_structs(w, &classes));
    try!(generate_interfaces_structs(w, &interfaces));

    try!(writeln!(w, ""));
    try!(writeln!(w, "extern \"C\" {{"));
    try!(functions::generate_records_funcs(w, env, &records));
    try!(functions::generate_classes_funcs(w, env, &classes));
    try!(functions::generate_interfaces_funcs(w, env, &interfaces));
    try!(functions::generate_other_funcs(w, env, &ns.functions));

    try!(writeln!(w, "\n}}"));

    Ok(())
}

fn generate_extern_crates<W: Write>(w: &mut W, env: &Env) -> Result<()>{
    for library_name in &env.config.external_libraries {
        try!(writeln!(w, "extern crate {0}_sys as {0}_ffi;", crate_name(library_name)));
    }

    Ok(())
}

fn prepare<T: Ord>(ns: &library::Namespace) -> Vec<&T>
where library::Type: MaybeRef<T> {
    let mut vec: Vec<&T> = Vec::with_capacity(ns.types.len());
    for typ in ns.types.iter().filter_map(|t| t.as_ref()) {
        if let Some(ref x) = typ.maybe_ref() {
            vec.push(x);
        }
    }
    vec.sort();
    vec
}

fn generate_aliases<W: Write>(w: &mut W, env: &Env, items: &[&library::Alias])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        let (comment, c_type) = match ffi_type(env, item.typ, &item.target_c_type) {
            Ok(x) => ("", x),
            Err(x) => ("//", x),
        };
        try!(writeln!(w, "{}pub type {} = {};", comment, item.c_identifier, c_type));
    }

    Ok(())
}

fn generate_bitfields<W: Write>(w: &mut W, items: &[&library::Bitfield])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        try!(writeln!(w, "bitflags! {{\n{}#[repr(C)]\n{0}flags {}: c_uint {{",
                      tabs(1), item.c_type));
        for member in &item.members {
            let val: i64 = member.value.parse().unwrap();
            try!(writeln!(w, "{}const {} = {},", tabs(2), member.c_identifier, val as u32));
        }
        try!(writeln!(w, "{}}}\n}}", tabs(1)));
        try!(writeln!(w, ""));
    }

    Ok(())
}

fn generate_constants<W: Write>(w: &mut W, env: &Env, constants: &[library::Constant]) -> Result<()> {
    try!(writeln!(w, ""));
    for constant in constants {
        let (mut comment, mut type_) = match parameter_rust_type(env, constant.typ, library::ParameterDirection::In) {
            Ok(x) => ("", x),
            Err(x) => ("//", x),
        };
        if env.type_status_sys(&format!("{}.{}", env.config.library_name,
            constant.name)).ignored() {
            comment = "//";
        }
        let mut value = constant.value.clone();
        if type_ == "&str" {
            type_ = "&'static str".into();
            value = format!("r##\"{}\"##", value);
        }
        try!(writeln!(w, "{}pub const {}:{} = {};", comment,
            constant.c_identifier, type_, value));
    }

    Ok(())
}

fn generate_enums<W: Write>(w: &mut W, items: &[&library::Enumeration])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        if item.members.len() == 1 {
            try!(writeln!(w, "pub type {} = c_int;", item.name));
            try!(writeln!(w, "pub const {}: {} = {};",
                          item.members[0].c_identifier, item.name, item.members[0].value));
            try!(writeln!(w, "pub type {} = {};", item.c_type, item.name));
            try!(writeln!(w, ""));
            continue;
        }

        let mut vals = HashMap::new();
        try!(writeln!(w, "#[derive(Clone, Copy, Debug, Eq, PartialEq)]\n#[repr(C)]"));
        try!(writeln!(w, "pub enum {} {{", item.c_type));
        for member in &item.members {
            if vals.get(&member.value).is_some() {
                continue;
            }
            try!(writeln!(w, "{}{} = {},",
                          tabs(1), &prepare_enum_member_name(&member.name), member.value));
            vals.insert(member.value.clone(), member.name.clone());
        }
        try!(writeln!(w, "}}"));
        for member in &item.members {
            try!(writeln!(w, "pub const {}: {} = {1}::{};", member.c_identifier, item.c_type,
                          &prepare_enum_member_name(vals.get(&member.value).unwrap())));
        }
        try!(writeln!(w, ""));
    }

    Ok(())
}

fn generate_unions<W: Write>(w: &mut W, items: &[&library::Union])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        if let Some(ref c_type) = item.c_type {
            try!(writeln!(w, "pub type {} = c_void; // union", c_type));
        }
    }
    try!(writeln!(w, ""));

    Ok(())
}

fn prepare_enum_member_name(name: &str) -> String {
    let cameled = name.to_camel();
    if name.chars().next().unwrap().is_digit(10) {
        format!("_{}", cameled)
    } else {
        cameled
    }
}

fn generate_classes_structs<W: Write>(w: &mut W, classes: &[&library::Class]) -> Result<()> {
    try!(writeln!(w, ""));
    for klass in classes {
        try!(writeln!(w, "#[repr(C)]\npub struct {};", klass.c_type));
    }

    Ok(())
}

fn generate_interfaces_structs<W: Write>(w: &mut W, interfaces: &[&library::Interface]) -> Result<()> {
    try!(writeln!(w, ""));
    for interface in interfaces {
        try!(writeln!(w, "#[repr(C)]\npub struct {};", interface.c_type));
    }

    Ok(())
}

fn generate_records<W: Write>(w: &mut W, env: &Env, records: &[&library::Record]) -> Result<()> {
    try!(writeln!(w, ""));
    for record in records {
        let mut lines = Vec::new();
        let mut commented = false;
        let mut truncated = false;
        for field in &record.fields {
            let is_union = env.library.type_(field.typ).maybe_ref_as::<library::Union>().is_some();
            let is_bits = field.bits.is_some();
            if !truncated && (is_union || is_bits) {
                warn!("Record `{}` field `{}` not expressible in Rust, truncated",
                      record.name, field.name);
                lines.push(format!("{}_truncated_record_marker: (),", tabs(1)));
                truncated = true;
            }
            if truncated {
                if is_union {
                    lines.push(format!("{}//union,", tabs(1)));
                }
                else {
                    let bits = field.bits.map(|n| format!(": {}", n)).unwrap_or("".into());
                    lines.push(
                        format!("{}//{}: {}{},", tabs(1), field.name,
                                field.c_type.as_ref().map(|s| &s[..]).unwrap_or("fn"), bits));
                };
                continue;
            }

            let vis = if field.private { "" } else { "pub " };

            if let Some(ref c_type) = field.c_type {
                let name = mangle_keywords(&*field.name);
                let c_type = ffi_type(env, field.typ, c_type);
                lines.push(format!("{}{}{}: {},", tabs(1), vis, name, c_type.as_str()));
                if c_type.is_err() {
                    commented = true;
                }
            }
            else {
                let name = mangle_keywords(&*field.name);
                if let Some(ref func) =
                        env.library.type_(field.typ).maybe_ref_as::<library::Function>() {
                    let (com, sig) = functions::function_signature(env, func, true);
                    lines.push(format!("{}{}{}: Option<unsafe extern \"C\" fn{}>,", tabs(1), vis, name, sig));
                    commented |= com;
                }
                else if let Some(c_type) = env.library.type_(field.typ).get_glib_name() {
                    warn!("Record `{}`, field `{}` missing c:type assumed `{}`",
                          record.name, field.name, c_type);
                    let c_type = ffi_type(env, field.typ, c_type);
                    lines.push(format!("{}{}{}: {},", tabs(1), vis, name, c_type.as_str()));
                    if c_type.is_err() {
                        commented = true;
                    }
                }
                else {
                    lines.push(format!("{}{}{}: [{:?} {}],", tabs(1),
                        vis, name, field.typ, field.typ.full_name(&env.library)));
                    commented = true;
                }
            }
        }
        let comment = if commented { "//" } else { "" };
        if lines.is_empty() {
            try!(writeln!(w, "{}#[repr(C)]\n{0}pub struct {};\n", comment, record.c_type));
        }
        else {
            try!(writeln!(w, "{}#[repr(C)]\n{0}pub struct {} {{", comment, record.c_type));
            for line in lines {
                try!(writeln!(w, "{}{}", comment, line));
            }
            try!(writeln!(w, "{}}}\n", comment));
        }
    }
    Ok(())
}
<commit_msg>sys: add a space in const formatting<commit_after>use std::collections::HashMap;
use std::fs;
use std::path::*;
use std::io::{Result, Write};
use case::CaseExt;

use analysis::rust_type::parameter_rust_type;
use env::Env;
use file_saver::*;
use library;
use nameutil::*;
use super::ffi_type::ffi_type;
use super::functions;
use super::statics;
use super::super::general::{self, tabs};
use traits::*;

pub fn generate(env: &Env) {
    println!("generating sys for {}", env.config.library_name);

    let path =  PathBuf::from(&env.config.target_path)
        .join(file_name_sys("lib"));

    let parent = path.parent().unwrap();
    //TODO: do only if not exists
    let _ = fs::create_dir(parent);

    println!("Generating file {:?}", path);
    save_to_file(&path, &mut |w| generate_lib(w, env));
}

fn generate_lib<W: Write>(w: &mut W, env: &Env) -> Result<()>{
    try!(general::start_comments(w, &env.config));
    try!(statics::begin(w));

    try!(generate_extern_crates(w, env));
    try!(statics::after_extern_crates(w));

    if env.config.library_name != "GLib" {
        try!(statics::use_glib_ffi(w));
    } else {
        try!(statics::only_for_glib(w));
    }
    if env.config.library_name == "Gtk" {
        try!(statics::only_for_gtk(w));
    }

    let ns = env.library.namespace(library::MAIN_NAMESPACE);
    let records = prepare(ns);
    let classes = prepare(ns);
    let interfaces = prepare(ns);

    try!(generate_aliases(w, env, &prepare(ns)));
    try!(generate_enums(w, &prepare(ns)));
    try!(generate_constants(w, env, &ns.constants));
    try!(generate_bitfields(w, &prepare(ns)));
    try!(generate_unions(w, &prepare(ns)));
    try!(functions::generate_callbacks(w, env, &prepare(ns)));
    try!(generate_records(w, env, &records));
    try!(generate_classes_structs(w, &classes));
    try!(generate_interfaces_structs(w, &interfaces));

    try!(writeln!(w, ""));
    try!(writeln!(w, "extern \"C\" {{"));
    try!(functions::generate_records_funcs(w, env, &records));
    try!(functions::generate_classes_funcs(w, env, &classes));
    try!(functions::generate_interfaces_funcs(w, env, &interfaces));
    try!(functions::generate_other_funcs(w, env, &ns.functions));

    try!(writeln!(w, "\n}}"));

    Ok(())
}

fn generate_extern_crates<W: Write>(w: &mut W, env: &Env) -> Result<()>{
    for library_name in &env.config.external_libraries {
        try!(writeln!(w, "extern crate {0}_sys as {0}_ffi;", crate_name(library_name)));
    }

    Ok(())
}

fn prepare<T: Ord>(ns: &library::Namespace) -> Vec<&T>
where library::Type: MaybeRef<T> {
    let mut vec: Vec<&T> = Vec::with_capacity(ns.types.len());
    for typ in ns.types.iter().filter_map(|t| t.as_ref()) {
        if let Some(ref x) = typ.maybe_ref() {
            vec.push(x);
        }
    }
    vec.sort();
    vec
}

fn generate_aliases<W: Write>(w: &mut W, env: &Env, items: &[&library::Alias])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        let (comment, c_type) = match ffi_type(env, item.typ, &item.target_c_type) {
            Ok(x) => ("", x),
            Err(x) => ("//", x),
        };
        try!(writeln!(w, "{}pub type {} = {};", comment, item.c_identifier, c_type));
    }

    Ok(())
}

fn generate_bitfields<W: Write>(w: &mut W, items: &[&library::Bitfield])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        try!(writeln!(w, "bitflags! {{\n{}#[repr(C)]\n{0}flags {}: c_uint {{",
                      tabs(1), item.c_type));
        for member in &item.members {
            let val: i64 = member.value.parse().unwrap();
            try!(writeln!(w, "{}const {} = {},", tabs(2), member.c_identifier, val as u32));
        }
        try!(writeln!(w, "{}}}\n}}", tabs(1)));
        try!(writeln!(w, ""));
    }

    Ok(())
}

fn generate_constants<W: Write>(w: &mut W, env: &Env, constants: &[library::Constant]) -> Result<()> {
    try!(writeln!(w, ""));
    for constant in constants {
        let (mut comment, mut type_) = match parameter_rust_type(env, constant.typ, library::ParameterDirection::In) {
            Ok(x) => ("", x),
            Err(x) => ("//", x),
        };
        if env.type_status_sys(&format!("{}.{}", env.config.library_name,
            constant.name)).ignored() {
            comment = "//";
        }
        let mut value = constant.value.clone();
        if type_ == "&str" {
            type_ = "&'static str".into();
            value = format!("r##\"{}\"##", value);
        }
        try!(writeln!(w, "{}pub const {}: {} = {};", comment,
            constant.c_identifier, type_, value));
    }

    Ok(())
}

fn generate_enums<W: Write>(w: &mut W, items: &[&library::Enumeration])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        if item.members.len() == 1 {
            try!(writeln!(w, "pub type {} = c_int;", item.name));
            try!(writeln!(w, "pub const {}: {} = {};",
                          item.members[0].c_identifier, item.name, item.members[0].value));
            try!(writeln!(w, "pub type {} = {};", item.c_type, item.name));
            try!(writeln!(w, ""));
            continue;
        }

        let mut vals = HashMap::new();
        try!(writeln!(w, "#[derive(Clone, Copy, Debug, Eq, PartialEq)]\n#[repr(C)]"));
        try!(writeln!(w, "pub enum {} {{", item.c_type));
        for member in &item.members {
            if vals.get(&member.value).is_some() {
                continue;
            }
            try!(writeln!(w, "{}{} = {},",
                          tabs(1), &prepare_enum_member_name(&member.name), member.value));
            vals.insert(member.value.clone(), member.name.clone());
        }
        try!(writeln!(w, "}}"));
        for member in &item.members {
            try!(writeln!(w, "pub const {}: {} = {1}::{};", member.c_identifier, item.c_type,
                          &prepare_enum_member_name(vals.get(&member.value).unwrap())));
        }
        try!(writeln!(w, ""));
    }

    Ok(())
}

fn generate_unions<W: Write>(w: &mut W, items: &[&library::Union])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        if let Some(ref c_type) = item.c_type {
            try!(writeln!(w, "pub type {} = c_void; // union", c_type));
        }
    }
    try!(writeln!(w, ""));

    Ok(())
}

fn prepare_enum_member_name(name: &str) -> String {
    let cameled = name.to_camel();
    if name.chars().next().unwrap().is_digit(10) {
        format!("_{}", cameled)
    } else {
        cameled
    }
}

fn generate_classes_structs<W: Write>(w: &mut W, classes: &[&library::Class]) -> Result<()> {
    try!(writeln!(w, ""));
    for klass in classes {
        try!(writeln!(w, "#[repr(C)]\npub struct {};", klass.c_type));
    }

    Ok(())
}

fn generate_interfaces_structs<W: Write>(w: &mut W, interfaces: &[&library::Interface]) -> Result<()> {
    try!(writeln!(w, ""));
    for interface in interfaces {
        try!(writeln!(w, "#[repr(C)]\npub struct {};", interface.c_type));
    }

    Ok(())
}

fn generate_records<W: Write>(w: &mut W, env: &Env, records: &[&library::Record]) -> Result<()> {
    try!(writeln!(w, ""));
    for record in records {
        let mut lines = Vec::new();
        let mut commented = false;
        let mut truncated = false;
        for field in &record.fields {
            let is_union = env.library.type_(field.typ).maybe_ref_as::<library::Union>().is_some();
            let is_bits = field.bits.is_some();
            if !truncated && (is_union || is_bits) {
                warn!("Record `{}` field `{}` not expressible in Rust, truncated",
                      record.name, field.name);
                lines.push(format!("{}_truncated_record_marker: (),", tabs(1)));
                truncated = true;
            }
            if truncated {
                if is_union {
                    lines.push(format!("{}//union,", tabs(1)));
                }
                else {
                    let bits = field.bits.map(|n| format!(": {}", n)).unwrap_or("".into());
                    lines.push(
                        format!("{}//{}: {}{},", tabs(1), field.name,
                                field.c_type.as_ref().map(|s| &s[..]).unwrap_or("fn"), bits));
                };
                continue;
            }

            let vis = if field.private { "" } else { "pub " };

            if let Some(ref c_type) = field.c_type {
                let name = mangle_keywords(&*field.name);
                let c_type = ffi_type(env, field.typ, c_type);
                lines.push(format!("{}{}{}: {},", tabs(1), vis, name, c_type.as_str()));
                if c_type.is_err() {
                    commented = true;
                }
            }
            else {
                let name = mangle_keywords(&*field.name);
                if let Some(ref func) =
                        env.library.type_(field.typ).maybe_ref_as::<library::Function>() {
                    let (com, sig) = functions::function_signature(env, func, true);
                    lines.push(format!("{}{}{}: Option<unsafe extern \"C\" fn{}>,", tabs(1), vis, name, sig));
                    commented |= com;
                }
                else if let Some(c_type) = env.library.type_(field.typ).get_glib_name() {
                    warn!("Record `{}`, field `{}` missing c:type assumed `{}`",
                          record.name, field.name, c_type);
                    let c_type = ffi_type(env, field.typ, c_type);
                    lines.push(format!("{}{}{}: {},", tabs(1), vis, name, c_type.as_str()));
                    if c_type.is_err() {
                        commented = true;
                    }
                }
                else {
                    lines.push(format!("{}{}{}: [{:?} {}],", tabs(1),
                        vis, name, field.typ, field.typ.full_name(&env.library)));
                    commented = true;
                }
            }
        }
        let comment = if commented { "//" } else { "" };
        if lines.is_empty() {
            try!(writeln!(w, "{}#[repr(C)]\n{0}pub struct {};\n", comment, record.c_type));
        }
        else {
            try!(writeln!(w, "{}#[repr(C)]\n{0}pub struct {} {{", comment, record.c_type));
            for line in lines {
                try!(writeln!(w, "{}{}", comment, line));
            }
            try!(writeln!(w, "{}}}\n", comment));
        }
    }
    Ok(())
}
<|endoftext|>


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

// This test case tests the incremental compilation hash (ICH) implementation
// for let expressions.

// The general pattern followed here is: Change one thing between rev1 and rev2
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.

// must-compile-successfully
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph

#![allow(warnings)]
#![feature(rustc_attrs)]
#![crate_type="rlib"]

// Change Name -----------------------------------------------------------------
#[cfg(cfail1)]
pub fn change_name() {
    let _x = 2u64;
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_dirty(label="MirValidated", cfg="cfail2")]
#[rustc_clean(label="MirValidated", cfg="cfail3")]
#[rustc_dirty(label="MirOptimized", cfg="cfail2")]
#[rustc_clean(label="MirOptimized", cfg="cfail3")]
#[rustc_clean(label="TypeckTables", cfg="cfail2")]
#[rustc_clean(label="TypeckTables", cfg="cfail3")]
#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
#[rustc_clean(label="FnSignature", cfg="cfail2")]
#[rustc_clean(label="FnSignature", cfg="cfail3")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
pub fn change_name() {
    let _y = 2u64;
}

// Add Type --------------------------------------------------------------------
#[cfg(cfail1)]
pub fn add_type() {
    let _x = 2u32;
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_clean(label="MirValidated", cfg="cfail2")]
#[rustc_clean(label="MirValidated", cfg="cfail3")]
#[rustc_clean(label="MirOptimized", cfg="cfail2")]
#[rustc_clean(label="MirOptimized", cfg="cfail3")]
#[rustc_dirty(label="TypeckTables", cfg="cfail2")]
#[rustc_clean(label="TypeckTables", cfg="cfail3")]
#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
#[rustc_clean(label="FnSignature", cfg="cfail2")]
#[rustc_clean(label="FnSignature", cfg="cfail3")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
pub fn add_type() {
    let _x: u32 = 2u32;
}

// Change Type -----------------------------------------------------------------
#[cfg(cfail1)]
pub fn change_type() {
    let _x: u64 = 2;
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_dirty(label="MirValidated", cfg="cfail2")]
#[rustc_clean(label="MirValidated", cfg="cfail3")]
#[rustc_dirty(label="MirOptimized", cfg="cfail2")]
#[rustc_clean(label="MirOptimized", cfg="cfail3")]
#[rustc_dirty(label="TypeckTables", cfg="cfail2")]
#[rustc_clean(label="TypeckTables", cfg="cfail3")]
#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
#[rustc_clean(label="FnSignature", cfg="cfail2")]
#[rustc_clean(label="FnSignature", cfg="cfail3")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
pub fn change_type() {
    let _x: u8 = 2;
}

// Change Mutability of Reference Type -----------------------------------------
#[cfg(cfail1)]
pub fn change_mutability_of_reference_type() {
    let _x: &u64;
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_dirty(label="MirValidated", cfg="cfail2")]
#[rustc_clean(label="MirValidated", cfg="cfail3")]
#[rustc_clean(label="MirOptimized", cfg="cfail2")]
#[rustc_clean(label="MirOptimized", cfg="cfail3")]
#[rustc_dirty(label="TypeckTables", cfg="cfail2")]
#[rustc_clean(label="TypeckTables", cfg="cfail3")]
#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
#[rustc_clean(label="FnSignature", cfg="cfail2")]
#[rustc_clean(label="FnSignature", cfg="cfail3")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
pub fn change_mutability_of_reference_type() {
    let _x: &mut u64;
}

// Change Mutability of Slot ---------------------------------------------------
#[cfg(cfail1)]
pub fn change_mutability_of_slot() {
    let mut _x: u64 = 0;
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_dirty(label="MirValidated", cfg="cfail2")]
#[rustc_clean(label="MirValidated", cfg="cfail3")]
#[rustc_dirty(label="MirOptimized", cfg="cfail2")]
#[rustc_clean(label="MirOptimized", cfg="cfail3")]
#[rustc_dirty(label="TypeckTables", cfg="cfail2")]
#[rustc_clean(label="TypeckTables", cfg="cfail3")]
#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
#[rustc_clean(label="FnSignature", cfg="cfail2")]
#[rustc_clean(label="FnSignature", cfg="cfail3")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
pub fn change_mutability_of_slot() {
    let _x: u64 = 0;
}

// Change Simple Binding to Pattern --------------------------------------------
#[cfg(cfail1)]
pub fn change_simple_binding_to_pattern() {
    let _x = (0u8, 'x');
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_dirty(label="MirValidated", cfg="cfail2")]
#[rustc_clean(label="MirValidated", cfg="cfail3")]
#[rustc_dirty(label="MirOptimized", cfg="cfail2")]
#[rustc_clean(label="MirOptimized", cfg="cfail3")]
#[rustc_dirty(label="TypeckTables", cfg="cfail2")]
#[rustc_clean(label="TypeckTables", cfg="cfail3")]
#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
#[rustc_clean(label="FnSignature", cfg="cfail2")]
#[rustc_clean(label="FnSignature", cfg="cfail3")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
pub fn change_simple_binding_to_pattern() {
    let (_a, _b) = (0u8, 'x');
}

// Change Name in Pattern ------------------------------------------------------
#[cfg(cfail1)]
pub fn change_name_in_pattern() {
    let (_a, _b) = (1u8, 'y');
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_dirty(label="MirValidated", cfg="cfail2")]
#[rustc_clean(label="MirValidated", cfg="cfail3")]
#[rustc_dirty(label="MirOptimized", cfg="cfail2")]
#[rustc_clean(label="MirOptimized", cfg="cfail3")]
#[rustc_clean(label="TypeckTables", cfg="cfail2")]
#[rustc_clean(label="TypeckTables", cfg="cfail3")]
#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
#[rustc_clean(label="FnSignature", cfg="cfail2")]
#[rustc_clean(label="FnSignature", cfg="cfail3")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
pub fn change_name_in_pattern() {
    let (_a, _c) = (1u8, 'y');
}

// Add `ref` in Pattern --------------------------------------------------------
#[cfg(cfail1)]
pub fn add_ref_in_pattern() {
    let (_a, _b) = (1u8, 'y');
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_dirty(label="MirValidated", cfg="cfail2")]
#[rustc_clean(label="MirValidated", cfg="cfail3")]
#[rustc_dirty(label="MirOptimized", cfg="cfail2")]
#[rustc_clean(label="MirOptimized", cfg="cfail3")]
#[rustc_dirty(label="TypeckTables", cfg="cfail2")]
#[rustc_clean(label="TypeckTables", cfg="cfail3")]
#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
#[rustc_clean(label="FnSignature", cfg="cfail2")]
#[rustc_clean(label="FnSignature", cfg="cfail3")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
pub fn add_ref_in_pattern() {
    let (ref _a, _b) = (1u8, 'y');
}

// Add `&` in Pattern ----------------------------------------------------------
#[cfg(cfail1)]
pub fn add_amp_in_pattern() {
    let (_a, _b) = (&1u8, 'y');
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_dirty(label="MirValidated", cfg="cfail2")]
#[rustc_clean(label="MirValidated", cfg="cfail3")]
#[rustc_dirty(label="MirOptimized", cfg="cfail2")]
#[rustc_clean(label="MirOptimized", cfg="cfail3")]
#[rustc_dirty(label="TypeckTables", cfg="cfail2")]
#[rustc_clean(label="TypeckTables", cfg="cfail3")]
pub fn add_amp_in_pattern() {
    let (&_a, _b) = (&1u8, 'y');
}

// Change Mutability of Binding in Pattern -------------------------------------
#[cfg(cfail1)]
pub fn change_mutability_of_binding_in_pattern() {
    let (_a, _b) = (99u8, 'q');
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_dirty(label="MirValidated", cfg="cfail2")]
#[rustc_clean(label="MirValidated", cfg="cfail3")]
#[rustc_dirty(label="MirOptimized", cfg="cfail2")]
#[rustc_clean(label="MirOptimized", cfg="cfail3")]
#[rustc_dirty(label="TypeckTables", cfg="cfail2")]
#[rustc_clean(label="TypeckTables", cfg="cfail3")]
#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
#[rustc_clean(label="FnSignature", cfg="cfail2")]
#[rustc_clean(label="FnSignature", cfg="cfail3")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
pub fn change_mutability_of_binding_in_pattern() {
    let (mut _a, _b) = (99u8, 'q');
}

// Add Initializer -------------------------------------------------------------
#[cfg(cfail1)]
pub fn add_initializer() {
    let _x: i16;
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_dirty(label="MirValidated", cfg="cfail2")]
#[rustc_clean(label="MirValidated", cfg="cfail3")]
#[rustc_dirty(label="MirOptimized", cfg="cfail2")]
#[rustc_clean(label="MirOptimized", cfg="cfail3")]
#[rustc_dirty(label="TypeckTables", cfg="cfail2")]
#[rustc_clean(label="TypeckTables", cfg="cfail3")]
#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
#[rustc_clean(label="FnSignature", cfg="cfail2")]
#[rustc_clean(label="FnSignature", cfg="cfail3")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
pub fn add_initializer() {
    let _x: i16 = 3i16;
}

// Change Initializer ----------------------------------------------------------
#[cfg(cfail1)]
pub fn change_initializer() {
    let _x = 4u16;
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
#[rustc_dirty(label="MirValidated", cfg="cfail2")]
#[rustc_clean(label="MirValidated", cfg="cfail3")]
#[rustc_dirty(label="MirOptimized", cfg="cfail2")]
#[rustc_clean(label="MirOptimized", cfg="cfail3")]
#[rustc_clean(label="TypeckTables", cfg="cfail2")]
#[rustc_clean(label="TypeckTables", cfg="cfail3")]
#[rustc_clean(label="TypeOfItem", cfg="cfail2")]
#[rustc_clean(label="TypeOfItem", cfg="cfail3")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
#[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
#[rustc_clean(label="FnSignature", cfg="cfail2")]
#[rustc_clean(label="FnSignature", cfg="cfail3")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
pub fn change_initializer() {
    let _x = 5u16;
}
<commit_msg>Rollup merge of #45987 - gaurikholkar:let-expr, r=michaelwoerister<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// This test case tests the incremental compilation hash (ICH) implementation
// for let expressions.

// The general pattern followed here is: Change one thing between rev1 and rev2
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.

// must-compile-successfully
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph

#![allow(warnings)]
#![feature(rustc_attrs)]
#![crate_type="rlib"]

// Change Name -----------------------------------------------------------------
#[cfg(cfail1)]
pub fn change_name() {
    let _x = 2u64;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn change_name() {
    let _y = 2u64;
}

// Add Type --------------------------------------------------------------------
#[cfg(cfail1)]
pub fn add_type() {
    let _x = 2u32;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn add_type() {
    let _x: u32 = 2u32;
}

// Change Type -----------------------------------------------------------------
#[cfg(cfail1)]
pub fn change_type() {
    let _x: u64 = 2;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_type() {
    let _x: u8 = 2;
}

// Change Mutability of Reference Type -----------------------------------------
#[cfg(cfail1)]
pub fn change_mutability_of_reference_type() {
    let _x: &u64;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_mutability_of_reference_type() {
    let _x: &mut u64;
}

// Change Mutability of Slot ---------------------------------------------------
#[cfg(cfail1)]
pub fn change_mutability_of_slot() {
    let mut _x: u64 = 0;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_mutability_of_slot() {
    let _x: u64 = 0;
}

// Change Simple Binding to Pattern --------------------------------------------
#[cfg(cfail1)]
pub fn change_simple_binding_to_pattern() {
    let _x = (0u8, 'x');
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_simple_binding_to_pattern() {
    let (_a, _b) = (0u8, 'x');
}

// Change Name in Pattern ------------------------------------------------------
#[cfg(cfail1)]
pub fn change_name_in_pattern() {
    let (_a, _b) = (1u8, 'y');
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_name_in_pattern() {
    let (_a, _c) = (1u8, 'y');
}

// Add `ref` in Pattern --------------------------------------------------------
#[cfg(cfail1)]
pub fn add_ref_in_pattern() {
    let (_a, _b) = (1u8, 'y');
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn add_ref_in_pattern() {
    let (ref _a, _b) = (1u8, 'y');
}

// Add `&` in Pattern ----------------------------------------------------------
#[cfg(cfail1)]
pub fn add_amp_in_pattern() {
    let (_a, _b) = (&1u8, 'y');
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn add_amp_in_pattern() {
    let (&_a, _b) = (&1u8, 'y');
}

// Change Mutability of Binding in Pattern -------------------------------------
#[cfg(cfail1)]
pub fn change_mutability_of_binding_in_pattern() {
    let (_a, _b) = (99u8, 'q');
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_mutability_of_binding_in_pattern() {
    let (mut _a, _b) = (99u8, 'q');
}

// Add Initializer -------------------------------------------------------------
#[cfg(cfail1)]
pub fn add_initializer() {
    let _x: i16;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn add_initializer() {
    let _x: i16 = 3i16;
}

// Change Initializer ----------------------------------------------------------
#[cfg(cfail1)]
pub fn change_initializer() {
    let _x = 4u16;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_initializer() {
    let _x = 5u16;
}
<|endoftext|>


<commit_before>use rustc_data_structures::fx::FxHashMap;
use rustc_errors::Applicability;
use rustc_hir::{self as hir, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::Symbol;

use if_chain::if_chain;

use crate::utils::{snippet, span_lint_and_sugg};

declare_clippy_lint! {
    /// **What it does:** Checks for struct constructors where the order of the field init
    /// shorthand in the constructor is inconsistent with the order in the struct definition.
    ///
    /// **Why is this bad?** It decreases readability and consistency.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// struct Foo {
    ///     x: i32,
    ///     y: i32,
    /// }
    /// let x = 1;
    /// let y = 2;
    /// Foo { y, x };
    /// ```
    ///
    /// Use instead:
    /// ```rust
    /// # struct Foo {
    /// #     x: i32,
    /// #     y: i32,
    /// # }
    /// # let x = 1;
    /// # let y = 2;
    /// Foo { x, y };
    /// ```
    pub INCONSISTENT_STRUCT_CONSTRUCTOR,
    style,
    "the order of the field init shorthand is inconsistent with the order in the struct definition"
}

declare_lint_pass!(InconsistentStructConstructor => [INCONSISTENT_STRUCT_CONSTRUCTOR]);

impl LateLintPass<'_> for InconsistentStructConstructor {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
        if_chain! {
            if let ExprKind::Struct(qpath, fields, base) = expr.kind;
            if let Some(def_id)  = cx.qpath_res(qpath, expr.hir_id).opt_def_id();
            let ty = cx.tcx.type_of(def_id);
            if let Some(adt_def) = ty.ty_adt_def();
            if adt_def.is_struct();
            if let Some(variant) = adt_def.variants.iter().next();
            if fields.iter().all(|f| f.is_shorthand);
            then {
                let mut def_order_map = FxHashMap::default();
                for (idx, field) in variant.fields.iter().enumerate() {
                    def_order_map.insert(field.ident.name, idx);
                }

                if is_consistent_order(fields, &def_order_map) {
                    return;
                }

                let mut ordered_fields: Vec<_> = fields.iter().map(|f| f.ident.name).collect();
                ordered_fields.sort_unstable_by_key(|id| def_order_map[id]);

                let mut fields_snippet = String::new();
                let (last_ident, idents) = ordered_fields.split_last().unwrap();
                for ident in idents {
                    fields_snippet.push_str(&format!("{}, ", ident));
                }
                fields_snippet.push_str(&format!("{}", last_ident));

                let base_snippet = if let Some(base) = base {
                        format!(", ..{}", snippet(cx, base.span, ".."))
                    } else {
                        "".to_string()
                    };

                let sugg = format!("{} {{ {}{} }}",
                    snippet(cx, qpath.span(), ".."),
                    fields_snippet,
                    base_snippet,
                    );

                span_lint_and_sugg(
                    cx,
                    INCONSISTENT_STRUCT_CONSTRUCTOR,
                    expr.span,
                    "inconsistent struct constructor",
                    "try",
                    sugg,
                    Applicability::MachineApplicable,
                )
            }
        }
    }
}

// Check whether the order of the fields in the constructor is consistent with the order in the
// definition.
fn is_consistent_order<'tcx>(fields: &'tcx [hir::Field<'tcx>], def_order_map: &FxHashMap<Symbol, usize>) -> bool {
    let mut cur_idx = usize::MIN;
    for f in fields {
        let next_idx = def_order_map[&f.ident.name];
        if cur_idx > next_idx {
            return false;
        }
        cur_idx = next_idx;
    }

    true
}
<commit_msg>Describe the order of fields in struct ctor doesn't affect the resulted instance<commit_after>use rustc_data_structures::fx::FxHashMap;
use rustc_errors::Applicability;
use rustc_hir::{self as hir, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::Symbol;

use if_chain::if_chain;

use crate::utils::{snippet, span_lint_and_sugg};

declare_clippy_lint! {
    /// **What it does:** Checks for struct constructors where the order of the field init
    /// shorthand in the constructor is inconsistent with the order in the struct definition.
    ///
    /// **Why is this bad?** Since the order of fields in a constructor doesn't affect the
    /// resulted instance as the below example indicates,
    ///
    /// ```rust
    /// #[derive(Debug, PartialEq, Eq)]
    /// struct Foo {
    ///     x: i32,
    ///     y: i32,
    /// }
    /// let x = 1;
    /// let y = 2;
    ///
    /// // This assertion never fails.
    /// assert_eq!(Foo { x, y }, Foo { y, x });
    /// ```
    ///
    /// inconsistent order means nothing and just decreases readability and consistency.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// struct Foo {
    ///     x: i32,
    ///     y: i32,
    /// }
    /// let x = 1;
    /// let y = 2;
    /// Foo { y, x };
    /// ```
    ///
    /// Use instead:
    /// ```rust
    /// # struct Foo {
    /// #     x: i32,
    /// #     y: i32,
    /// # }
    /// # let x = 1;
    /// # let y = 2;
    /// Foo { x, y };
    /// ```
    pub INCONSISTENT_STRUCT_CONSTRUCTOR,
    style,
    "the order of the field init shorthand is inconsistent with the order in the struct definition"
}

declare_lint_pass!(InconsistentStructConstructor => [INCONSISTENT_STRUCT_CONSTRUCTOR]);

impl LateLintPass<'_> for InconsistentStructConstructor {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
        if_chain! {
            if let ExprKind::Struct(qpath, fields, base) = expr.kind;
            if let Some(def_id)  = cx.qpath_res(qpath, expr.hir_id).opt_def_id();
            let ty = cx.tcx.type_of(def_id);
            if let Some(adt_def) = ty.ty_adt_def();
            if adt_def.is_struct();
            if let Some(variant) = adt_def.variants.iter().next();
            if fields.iter().all(|f| f.is_shorthand);
            then {
                let mut def_order_map = FxHashMap::default();
                for (idx, field) in variant.fields.iter().enumerate() {
                    def_order_map.insert(field.ident.name, idx);
                }

                if is_consistent_order(fields, &def_order_map) {
                    return;
                }

                let mut ordered_fields: Vec<_> = fields.iter().map(|f| f.ident.name).collect();
                ordered_fields.sort_unstable_by_key(|id| def_order_map[id]);

                let mut fields_snippet = String::new();
                let (last_ident, idents) = ordered_fields.split_last().unwrap();
                for ident in idents {
                    fields_snippet.push_str(&format!("{}, ", ident));
                }
                fields_snippet.push_str(&last_ident.to_string());

                let base_snippet = if let Some(base) = base {
                        format!(", ..{}", snippet(cx, base.span, ".."))
                    } else {
                        String::new()
                    };

                let sugg = format!("{} {{ {}{} }}",
                    snippet(cx, qpath.span(), ".."),
                    fields_snippet,
                    base_snippet,
                    );

                span_lint_and_sugg(
                    cx,
                    INCONSISTENT_STRUCT_CONSTRUCTOR,
                    expr.span,
                    "inconsistent struct constructor",
                    "try",
                    sugg,
                    Applicability::MachineApplicable,
                )
            }
        }
    }
}

// Check whether the order of the fields in the constructor is consistent with the order in the
// definition.
fn is_consistent_order<'tcx>(fields: &'tcx [hir::Field<'tcx>], def_order_map: &FxHashMap<Symbol, usize>) -> bool {
    let mut cur_idx = usize::MIN;
    for f in fields {
        let next_idx = def_order_map[&f.ident.name];
        if cur_idx > next_idx {
            return false;
        }
        cur_idx = next_idx;
    }

    true
}
<|endoftext|>


<commit_before>use std::collections::{VecDeque, HashSet};

use turtle::{Turtle, thread_rng, Rng};
use maze::Maze;

const SOLUTION_COLOR: &str = "#4CAF50";
const BACKTRACK_COLOR: &str = "#F44336";

/// Visually solve the maze by physically moving the turtle through it
pub fn solve(turtle: &mut Turtle, maze: Maze, cell_width: f64, cell_height: f64) {
    turtle.set_pen_color(SOLUTION_COLOR);

    let mut visited = HashSet::<(usize, usize)>::new();
    // Keeps track of where we move as we go there
    // Positions are removed as we backtrack
    let mut path_stack = VecDeque::<(usize, usize)>::new();
    let mut current = (0, 0);

    let mut rng = thread_rng();
    loop {
        if visited.contains(&current) {
            continue;
        }
        visited.insert(current);

        if current == maze.finish() {
            break;
        }

        // We force the compiler to copy here so that we do not get a borrow checker error since
        // current is mutated below
        let curr = current;
        let mut unvisited = maze.adjacent_cells(current).into_iter()
            .filter(|p| maze.is_open_between(curr, *p))
            .filter(|p| !visited.contains(p))
            .peekable();

        if unvisited.peek().is_none() {
            // Dead end, start backtracking until we have unvisited adjacents
            loop {
                let previous = match path_stack.pop_back() {
                    Some(pos) => pos,
                    None => unreachable!("Backtracked to the beginning. Could not find solution for maze!"),
                };
                // Animate to previous
                turtle.set_pen_color(BACKTRACK_COLOR);

                // If previous has unvisited adjacents, make it the current and break this loop
                // Otherwise keep going
            }
        }
        else {
            path_stack.push_back(current);

            let mut unvisited = unvisited.collect::<Vec<_>>();
            rng.shuffle(&mut unvisited);

            let next = *unvisited.first().unwrap();
            move_to(turtle, current, next, cell_width, cell_height);
            current = next;
        }
    }
}

fn move_to(
    turtle: &mut Turtle,
    (curr_row, curr_col): (usize, usize),
    (next_row, next_col): (usize, usize),
    cell_width: f64,
    cell_height: f64,
) {
    let delta = (next_row as isize - curr_row as isize, next_col as isize - curr_col as isize);
    let (target_heading, distance) = match delta {
        // go north
        (-1, 0) => (90.0, cell_height),
        // go east
        (0, 1) => (0.0, cell_width),
        // go south
        (1, 0) => (270.0, cell_height),
        // go west
        (0, -1) => (180.0, cell_width),
        _ => unreachable!("Attempt to move to non-adjacent cell"),
    };

    let heading = turtle.heading();
    // Find the amount we need to turn to reach the target heading based on our current heading
    let angle = target_heading - heading;
    // Normalize the angle to be between -180 and 179 so that we rotate as little as possible
    // Formula from: https://stackoverflow.com/a/24234924/551904
    let angle = angle - 360.0 * ((angle + 180.0) / 360.0).floor();

    turtle.left(angle);
    turtle.forward(distance);
}
<commit_msg>Added backtracking. Turtle can now fully solve the maze!<commit_after>use std::collections::{VecDeque, HashSet};

use turtle::{Turtle, thread_rng, Rng};
use maze::Maze;

const SOLUTION_COLOR: &str = "#4CAF50";
const BACKTRACK_COLOR: &str = "#F44336";

/// Visually solve the maze by physically moving the turtle through it
pub fn solve(turtle: &mut Turtle, maze: Maze, cell_width: f64, cell_height: f64) {
    turtle.set_pen_color(SOLUTION_COLOR);

    let mut visited = HashSet::<(usize, usize)>::new();
    // Keeps track of where we move as we go there
    // Positions are removed as we backtrack
    let mut path_stack = VecDeque::<(usize, usize)>::new();
    let mut current = (0, 0);

    let mut rng = thread_rng();
    loop {
        visited.insert(current);

        if current == maze.finish() {
            break;
        }

        let mut unvisited = unvisited_open_adjacents(&maze, &visited, current);
        rng.shuffle(&mut unvisited);

        if unvisited.is_empty() {
            // Dead end, start backtracking until we have unvisited adjacents
            turtle.set_pen_color(BACKTRACK_COLOR);
            loop {
                let previous = match path_stack.pop_back() {
                    Some(pos) => pos,
                    None => unreachable!("Backtracked to the beginning. Could not find solution for maze!"),
                };

                move_to(turtle, current, previous, cell_width, cell_height);
                current = previous;

                let unvisited = unvisited_open_adjacents(&maze, &visited, previous);
                if !unvisited.is_empty() {
                    break;
                }
            }
            turtle.set_pen_color(SOLUTION_COLOR);
        }
        else {
            path_stack.push_back(current);

            let next = *unvisited.first().unwrap();
            move_to(turtle, current, next, cell_width, cell_height);
            current = next;
        }
    }
}

fn unvisited_open_adjacents(maze: &Maze, visited: &HashSet<(usize, usize)>, position: (usize, usize)) -> Vec<(usize, usize)> {
    maze.adjacent_cells(position).into_iter()
        .filter(|p| maze.is_open_between(position, *p))
        .filter(|p| !visited.contains(p))
        .collect()
}

fn move_to(
    turtle: &mut Turtle,
    (curr_row, curr_col): (usize, usize),
    (next_row, next_col): (usize, usize),
    cell_width: f64,
    cell_height: f64,
) {
    let delta = (next_row as isize - curr_row as isize, next_col as isize - curr_col as isize);
    let (target_heading, distance) = match delta {
        // go north
        (-1, 0) => (90.0, cell_height),
        // go east
        (0, 1) => (0.0, cell_width),
        // go south
        (1, 0) => (270.0, cell_height),
        // go west
        (0, -1) => (180.0, cell_width),
        _ => unreachable!("Attempt to move to non-adjacent cell"),
    };

    let heading = turtle.heading();
    // Find the amount we need to turn to reach the target heading based on our current heading
    let angle = target_heading - heading;
    // Normalize the angle to be between -180 and 179 so that we rotate as little as possible
    // Formula from: https://stackoverflow.com/a/24234924/551904
    let angle = angle - 360.0 * ((angle + 180.0) / 360.0).floor();

    turtle.left(angle);
    turtle.forward(distance);
}
<|endoftext|>


<commit_before>//! An asynchronous, pipelined, PostgreSQL client.
//!
//! # Example
//!
//! ```no_run
//! use futures::FutureExt;
//! use tokio_postgres::{NoTls, Error, Row};
//!
//! # #[cfg(not(feature = "runtime"))] fn main() {}
//! # #[cfg(feature = "runtime")]
//! #[tokio::main] // By default, tokio_postgres uses the tokio crate as its runtime.
//! async fn main() -> Result<(), Error> {
//!     // Connect to the database.
//!     let (mut client, connection) =
//!         tokio_postgres::connect("host=localhost user=postgres", NoTls).await?;
//!
//!     // The connection object performs the actual communication with the database,
//!     // so spawn it off to run on its own.
//!     let connection = connection.map(|r| {
//!         if let Err(e) = r {
//!             eprintln!("connection error: {}", e);
//!         }
//!     });
//!     tokio::spawn(connection);
//!
//!     // Now we can prepare a simple statement that just returns its parameter.
//!     let stmt = client.prepare("SELECT $1::TEXT").await?;
//!
//!     // And then execute it, returning a Stream of Rows which we collect into a Vec.
//!     let rows: Vec<Row> = client
//!         .query(&stmt, &[&"hello world"])
//!         .await?;
//!
//!     // Now we can check that we got back the same string we sent over.
//!     let value: &str = rows[0].get(0);
//!     assert_eq!(value, "hello world");
//!
//!     Ok(())
//! }
//! ```
//!
//! # Behavior
//!
//! Calling a method like `Client::query` on its own does nothing. The associated request is not sent to the database
//! until the future returned by the method is first polled. Requests are executed in the order that they are first
//! polled, not in the order that their futures are created.
//!
//! # Pipelining
//!
//! The client supports *pipelined* requests. Pipelining can improve performance in use cases in which multiple,
//! independent queries need to be executed. In a traditional workflow, each query is sent to the server after the
//! previous query completes. In contrast, pipelining allows the client to send all of the queries to the server up
//! front, minimizing time spent by one side waiting for the other to finish sending data:
//!
//! ```not_rust
//!             Sequential                              Pipelined
//! | Client         | Server          |    | Client         | Server          |
//! |----------------|-----------------|    |----------------|-----------------|
//! | send query 1   |                 |    | send query 1   |                 |
//! |                | process query 1 |    | send query 2   | process query 1 |
//! | receive rows 1 |                 |    | send query 3   | process query 2 |
//! | send query 2   |                 |    | receive rows 1 | process query 3 |
//! |                | process query 2 |    | receive rows 2 |                 |
//! | receive rows 2 |                 |    | receive rows 3 |                 |
//! | send query 3   |                 |
//! |                | process query 3 |
//! | receive rows 3 |                 |
//! ```
//!
//! In both cases, the PostgreSQL server is executing the queries sequentially - pipelining just allows both sides of
//! the connection to work concurrently when possible.
//!
//! Pipelining happens automatically when futures are polled concurrently (for example, by using the futures `join`
//! combinator):
//!
//! ```rust
//! use futures::future;
//! use std::future::Future;
//! use tokio_postgres::{Client, Error, Statement};
//!
//! async fn pipelined_prepare(
//!     client: &Client,
//! ) -> Result<(Statement, Statement), Error>
//! {
//!     future::try_join(
//!         client.prepare("SELECT * FROM foo"),
//!         client.prepare("INSERT INTO bar (id, name) VALUES ($1, $2)")
//!     ).await
//! }
//! ```
//!
//! # Runtime
//!
//! The client works with arbitrary `AsyncRead + AsyncWrite` streams. Convenience APIs are provided to handle the
//! connection process, but these are gated by the `runtime` Cargo feature, which is enabled by default. If disabled,
//! all dependence on the tokio runtime is removed.
//!
//! # SSL/TLS support
//!
//! TLS support is implemented via external libraries. `Client::connect` and `Config::connect` take a TLS implementation
//! as an argument. The `NoTls` type in this crate can be used when TLS is not required. Otherwise, the
//! `postgres-openssl` and `postgres-native-tls` crates provide implementations backed by the `openssl` and `native-tls`
//! crates, respectively.
#![doc(html_root_url = "https://docs.rs/tokio-postgres/0.5")]
#![warn(rust_2018_idioms, clippy::all, missing_docs)]

pub use crate::client::Client;
pub use crate::config::Config;
pub use crate::connection::Connection;
use crate::error::DbError;
pub use crate::error::Error;
pub use crate::portal::Portal;
pub use crate::query::RowStream;
pub use crate::row::{Row, SimpleQueryRow};
pub use crate::simple_query::SimpleQueryStream;
#[cfg(feature = "runtime")]
pub use crate::socket::Socket;
pub use crate::statement::{Column, Statement};
#[cfg(feature = "runtime")]
use crate::tls::MakeTlsConnect;
pub use crate::tls::NoTls;
pub use crate::to_statement::ToStatement;
pub use crate::transaction::Transaction;
use crate::types::ToSql;

mod bind;
#[cfg(feature = "runtime")]
mod cancel_query;
mod cancel_query_raw;
mod client;
mod codec;
pub mod config;
#[cfg(feature = "runtime")]
mod connect;
mod connect_raw;
#[cfg(feature = "runtime")]
mod connect_socket;
mod connect_tls;
mod connection;
mod copy_in;
mod copy_out;
pub mod error;
mod maybe_tls_stream;
mod portal;
mod prepare;
mod query;
pub mod row;
mod simple_query;
#[cfg(feature = "runtime")]
mod socket;
mod statement;
pub mod tls;
mod to_statement;
mod transaction;
pub mod types;

/// A convenience function which parses a connection string and connects to the database.
///
/// See the documentation for [`Config`] for details on the connection string format.
///
/// Requires the `runtime` Cargo feature (enabled by default).
///
/// [`Config`]: config/struct.Config.html
#[cfg(feature = "runtime")]
pub async fn connect<T>(
    config: &str,
    tls: T,
) -> Result<(Client, Connection<Socket, T::Stream>), Error>
where
    T: MakeTlsConnect<Socket>,
{
    let config = config.parse::<Config>()?;
    config.connect(tls).await
}

/// An asynchronous notification.
#[derive(Clone, Debug)]
pub struct Notification {
    process_id: i32,
    channel: String,
    payload: String,
}

impl Notification {
    /// The process ID of the notifying backend process.
    pub fn process_id(&self) -> i32 {
        self.process_id
    }

    /// The name of the channel that the notify has been raised on.
    pub fn channel(&self) -> &str {
        &self.channel
    }

    /// The "payload" string passed from the notifying process.
    pub fn payload(&self) -> &str {
        &self.payload
    }
}

/// An asynchronous message from the server.
#[allow(clippy::large_enum_variant)]
pub enum AsyncMessage {
    /// A notice.
    ///
    /// Notices use the same format as errors, but aren't "errors" per-se.
    Notice(DbError),
    /// A notification.
    ///
    /// Connections can subscribe to notifications with the `LISTEN` command.
    Notification(Notification),
    #[doc(hidden)]
    __NonExhaustive,
}

/// Message returned by the `SimpleQuery` stream.
pub enum SimpleQueryMessage {
    /// A row of data.
    Row(SimpleQueryRow),
    /// A statement in the query has completed.
    ///
    /// The number of rows modified or selected is returned.
    CommandComplete(u64),
    #[doc(hidden)]
    __NonExhaustive,
}

fn slice_iter<'a>(
    s: &'a [&'a (dyn ToSql + Sync)],
) -> impl ExactSizeIterator<Item = &'a dyn ToSql> + 'a {
    s.iter().map(|s| *s as _)
}
<commit_msg>Clean up tokio-postgres example a bit<commit_after>//! An asynchronous, pipelined, PostgreSQL client.
//!
//! # Example
//!
//! ```no_run
//! use tokio_postgres::{NoTls, Error, Row};
//!
//! # #[cfg(not(feature = "runtime"))] fn main() {}
//! # #[cfg(feature = "runtime")]
//! #[tokio::main] // By default, tokio_postgres uses the tokio crate as its runtime.
//! async fn main() -> Result<(), Error> {
//!     // Connect to the database.
//!     let (mut client, connection) =
//!         tokio_postgres::connect("host=localhost user=postgres", NoTls).await?;
//!
//!     // The connection object performs the actual communication with the database,
//!     // so spawn it off to run on its own.
//!     tokio::spawn(async move {
//!         if let Err(e) = connection.await {
//!             eprintln!("connection error: {}", e);
//!         }
//!     });
//!
//!     // Now we can prepare a simple statement that just returns its parameter.
//!     let stmt = client.prepare("SELECT $1::TEXT").await?;
//!
//!     // And then execute it, returning a list of the resulting rows.
//!     let rows = client
//!         .query(&stmt, &[&"hello world"])
//!         .await?;
//!
//!     // Now we can check that we got back the same string we sent over.
//!     let value: &str = rows[0].get(0);
//!     assert_eq!(value, "hello world");
//!
//!     Ok(())
//! }
//! ```
//!
//! # Behavior
//!
//! Calling a method like `Client::query` on its own does nothing. The associated request is not sent to the database
//! until the future returned by the method is first polled. Requests are executed in the order that they are first
//! polled, not in the order that their futures are created.
//!
//! # Pipelining
//!
//! The client supports *pipelined* requests. Pipelining can improve performance in use cases in which multiple,
//! independent queries need to be executed. In a traditional workflow, each query is sent to the server after the
//! previous query completes. In contrast, pipelining allows the client to send all of the queries to the server up
//! front, minimizing time spent by one side waiting for the other to finish sending data:
//!
//! ```not_rust
//!             Sequential                              Pipelined
//! | Client         | Server          |    | Client         | Server          |
//! |----------------|-----------------|    |----------------|-----------------|
//! | send query 1   |                 |    | send query 1   |                 |
//! |                | process query 1 |    | send query 2   | process query 1 |
//! | receive rows 1 |                 |    | send query 3   | process query 2 |
//! | send query 2   |                 |    | receive rows 1 | process query 3 |
//! |                | process query 2 |    | receive rows 2 |                 |
//! | receive rows 2 |                 |    | receive rows 3 |                 |
//! | send query 3   |                 |
//! |                | process query 3 |
//! | receive rows 3 |                 |
//! ```
//!
//! In both cases, the PostgreSQL server is executing the queries sequentially - pipelining just allows both sides of
//! the connection to work concurrently when possible.
//!
//! Pipelining happens automatically when futures are polled concurrently (for example, by using the futures `join`
//! combinator):
//!
//! ```rust
//! use futures::future;
//! use std::future::Future;
//! use tokio_postgres::{Client, Error, Statement};
//!
//! async fn pipelined_prepare(
//!     client: &Client,
//! ) -> Result<(Statement, Statement), Error>
//! {
//!     future::try_join(
//!         client.prepare("SELECT * FROM foo"),
//!         client.prepare("INSERT INTO bar (id, name) VALUES ($1, $2)")
//!     ).await
//! }
//! ```
//!
//! # Runtime
//!
//! The client works with arbitrary `AsyncRead + AsyncWrite` streams. Convenience APIs are provided to handle the
//! connection process, but these are gated by the `runtime` Cargo feature, which is enabled by default. If disabled,
//! all dependence on the tokio runtime is removed.
//!
//! # SSL/TLS support
//!
//! TLS support is implemented via external libraries. `Client::connect` and `Config::connect` take a TLS implementation
//! as an argument. The `NoTls` type in this crate can be used when TLS is not required. Otherwise, the
//! `postgres-openssl` and `postgres-native-tls` crates provide implementations backed by the `openssl` and `native-tls`
//! crates, respectively.
#![doc(html_root_url = "https://docs.rs/tokio-postgres/0.5")]
#![warn(rust_2018_idioms, clippy::all, missing_docs)]

pub use crate::client::Client;
pub use crate::config::Config;
pub use crate::connection::Connection;
use crate::error::DbError;
pub use crate::error::Error;
pub use crate::portal::Portal;
pub use crate::query::RowStream;
pub use crate::row::{Row, SimpleQueryRow};
pub use crate::simple_query::SimpleQueryStream;
#[cfg(feature = "runtime")]
pub use crate::socket::Socket;
pub use crate::statement::{Column, Statement};
#[cfg(feature = "runtime")]
use crate::tls::MakeTlsConnect;
pub use crate::tls::NoTls;
pub use crate::to_statement::ToStatement;
pub use crate::transaction::Transaction;
use crate::types::ToSql;

mod bind;
#[cfg(feature = "runtime")]
mod cancel_query;
mod cancel_query_raw;
mod client;
mod codec;
pub mod config;
#[cfg(feature = "runtime")]
mod connect;
mod connect_raw;
#[cfg(feature = "runtime")]
mod connect_socket;
mod connect_tls;
mod connection;
mod copy_in;
mod copy_out;
pub mod error;
mod maybe_tls_stream;
mod portal;
mod prepare;
mod query;
pub mod row;
mod simple_query;
#[cfg(feature = "runtime")]
mod socket;
mod statement;
pub mod tls;
mod to_statement;
mod transaction;
pub mod types;

/// A convenience function which parses a connection string and connects to the database.
///
/// See the documentation for [`Config`] for details on the connection string format.
///
/// Requires the `runtime` Cargo feature (enabled by default).
///
/// [`Config`]: config/struct.Config.html
#[cfg(feature = "runtime")]
pub async fn connect<T>(
    config: &str,
    tls: T,
) -> Result<(Client, Connection<Socket, T::Stream>), Error>
where
    T: MakeTlsConnect<Socket>,
{
    let config = config.parse::<Config>()?;
    config.connect(tls).await
}

/// An asynchronous notification.
#[derive(Clone, Debug)]
pub struct Notification {
    process_id: i32,
    channel: String,
    payload: String,
}

impl Notification {
    /// The process ID of the notifying backend process.
    pub fn process_id(&self) -> i32 {
        self.process_id
    }

    /// The name of the channel that the notify has been raised on.
    pub fn channel(&self) -> &str {
        &self.channel
    }

    /// The "payload" string passed from the notifying process.
    pub fn payload(&self) -> &str {
        &self.payload
    }
}

/// An asynchronous message from the server.
#[allow(clippy::large_enum_variant)]
pub enum AsyncMessage {
    /// A notice.
    ///
    /// Notices use the same format as errors, but aren't "errors" per-se.
    Notice(DbError),
    /// A notification.
    ///
    /// Connections can subscribe to notifications with the `LISTEN` command.
    Notification(Notification),
    #[doc(hidden)]
    __NonExhaustive,
}

/// Message returned by the `SimpleQuery` stream.
pub enum SimpleQueryMessage {
    /// A row of data.
    Row(SimpleQueryRow),
    /// A statement in the query has completed.
    ///
    /// The number of rows modified or selected is returned.
    CommandComplete(u64),
    #[doc(hidden)]
    __NonExhaustive,
}

fn slice_iter<'a>(
    s: &'a [&'a (dyn ToSql + Sync)],
) -> impl ExactSizeIterator<Item = &'a dyn ToSql> + 'a {
    s.iter().map(|s| *s as _)
}
<|endoftext|>


<commit_before>//! Provides an interface to output sound to the user's speakers.
//!
//! It consists of two main types: `SoundData` is just raw sound data,
//! and a `Source` is a `SoundData` connected to a particular sound
//! channel.

use std::fmt;
use std::io;
use std::io::Read;
use std::path;

use std::sync::Arc;

use rodio;

use context::Context;
use GameError;
use GameResult;

/// A struct that contains all information for tracking sound info.
///
/// You generally don't have to create this yourself, it will be part
/// of your `Context` object.
pub struct AudioContext {
    endpoint: rodio::Endpoint,
}

impl AudioContext {
    /// Create new AudioContext.
    pub fn new() -> GameResult<AudioContext> {
        let error = GameError::AudioError(String::from(
            "Could not initialize sound system (for \
             some reason)",
        ));
        // This is deprecated in cpal but not in the most recent rodio (0.5.2) yet.
        #[allow(deprecated)]
        let e = rodio::get_default_endpoint().ok_or(error)?;
        Ok(AudioContext { endpoint: e })
    }
}

impl fmt::Debug for AudioContext {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<AudioContext: {:p}>", self)
    }
}

/// Static sound data stored in memory.
/// It is Arc'ed, so cheap to clone.
#[derive(Clone, Debug)]
pub struct SoundData(Arc<Vec<u8>>);

impl SoundData {
    /// Copies the data in the given slice into a new SoundData object.
    pub fn from_bytes(data: &[u8]) -> Self {
        SoundData::from(Vec::from(data))
    }

    /// Creates a SoundData from any Read object; this involves
    /// copying it into a buffer.
    pub fn from_read<R>(reader: &mut R) -> GameResult<Self>
    where
        R: Read,
    {
        let mut buffer = Vec::new();
        reader.read_to_end(&mut buffer)?;

        Ok(SoundData::from(buffer))
    }
}

impl From<Vec<u8>> for SoundData {
    fn from(v: Vec<u8>) -> Self {
        SoundData(Arc::new(v))
    }
}

impl AsRef<[u8]> for SoundData {
    fn as_ref(&self) -> &[u8] {
        self.0.as_ref().as_ref()
    }
}

/// A source of audio data connected to a particular `Channel`.
/// Will stop playing when dropped.
// TODO: Check and see if this matches Love2d's semantics!
// Eventually it might read from a streaming decoder of some kind,
// but for now it is just an in-memory SoundData structure.
// The source of a rodio decoder must be Send, which something
// that contains a reference to a ZipFile is not, so we are going
// to just slurp all the data into memory for now.
// There's really a lot of work that needs to be done here, since
// rodio has gotten better (if still somewhat arcane) and our filesystem
// code has done the data-slurping-from-zip's for us
// but for now it works.
pub struct Source {
    data: io::Cursor<SoundData>,
    sink: rodio::Sink,
}

impl Source {
    /// Create a new Source from the given file.
    pub fn new<P: AsRef<path::Path>>(context: &mut Context, path: P) -> GameResult<Self> {
        let path = path.as_ref();
        let data = {
            let file = &mut context.filesystem.open(path)?;
            SoundData::from_read(file)?
        };
        Source::from_data(context, data)
    }

    /// Creates a new Source using the given SoundData object.
    pub fn from_data(context: &mut Context, data: SoundData) -> GameResult<Self> {
        let sink = rodio::Sink::new(&context.audio_context.endpoint);
        let cursor = io::Cursor::new(data);
        Ok(Source {
            data: cursor,
            sink: sink,
        })
    }

    /// Plays the Source.
    pub fn play(&self) -> GameResult<()> {
        // Creating a new Decoder each time seems a little messy,
        // since it may do checking and data-type detection that is
        // redundant, but it's not super expensive.
        // See https://github.com/ggez/ggez/issues/98 for discussion
        let cursor = self.data.clone();
        let decoder = rodio::Decoder::new(cursor)?;
        self.sink.append(decoder);
        Ok(())
    }

    /// Pauses playback
    pub fn pause(&self) {
        self.sink.pause()
    }

    /// Resumes playback
    pub fn resume(&self) {
        self.sink.play()
    }

    /// Stops playback
    pub fn stop(&self) {
        self.sink.stop()
    }

    /// Gets the current volume
    pub fn volume(&self) -> f32 {
        self.sink.volume()
    }

    /// Sets the current volume
    pub fn set_volume(&mut self, value: f32) {
        self.sink.set_volume(value)
    }

    /// Get whether or not the source is paused
    pub fn paused(&self) -> bool {
        self.sink.is_paused()
    }

    /// Get whether or not the source is playing
    pub fn playing(&self) -> bool {
        !self.paused() // && !self.stopped()
    }
}

impl fmt::Debug for Source {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<Audio source: {:p}>", self)
    }
}

// TODO: global start, stop, volume?
<commit_msg>Use boxed slice for SoundData storage<commit_after>//! Provides an interface to output sound to the user's speakers.
//!
//! It consists of two main types: `SoundData` is just raw sound data,
//! and a `Source` is a `SoundData` connected to a particular sound
//! channel.

use std::fmt;
use std::io;
use std::io::Read;
use std::path;

use std::sync::Arc;

use rodio;

use context::Context;
use GameError;
use GameResult;

/// A struct that contains all information for tracking sound info.
///
/// You generally don't have to create this yourself, it will be part
/// of your `Context` object.
pub struct AudioContext {
    endpoint: rodio::Endpoint,
}

impl AudioContext {
    /// Create new AudioContext.
    pub fn new() -> GameResult<AudioContext> {
        let error = GameError::AudioError(String::from(
            "Could not initialize sound system (for \
             some reason)",
        ));
        // This is deprecated in cpal but not in the most recent rodio (0.5.2) yet.
        #[allow(deprecated)]
        let e = rodio::get_default_endpoint().ok_or(error)?;
        Ok(AudioContext { endpoint: e })
    }
}

impl fmt::Debug for AudioContext {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<AudioContext: {:p}>", self)
    }
}

/// Static sound data stored in memory.
/// It is Arc'ed, so cheap to clone.
#[derive(Clone, Debug)]
pub struct SoundData(Arc<Box<[u8]>>);

impl SoundData {
    /// Copies the data in the given slice into a new SoundData object.
    pub fn from_bytes(data: &[u8]) -> Self {
        SoundData::from(Vec::from(data))
    }

    /// Creates a SoundData from any Read object; this involves
    /// copying it into a buffer.
    pub fn from_read<R>(reader: &mut R) -> GameResult<Self>
    where
        R: Read,
    {
        let mut buffer = Vec::new();
        reader.read_to_end(&mut buffer)?;

        Ok(SoundData::from(buffer))
    }
}

impl From<Vec<u8>> for SoundData {
    fn from(v: Vec<u8>) -> Self {
        SoundData(Arc::new(v.into_boxed_slice()))
    }
}

impl AsRef<[u8]> for SoundData {
    fn as_ref(&self) -> &[u8] {
        self.0.as_ref().as_ref()
    }
}

/// A source of audio data connected to a particular `Channel`.
/// Will stop playing when dropped.
// TODO: Check and see if this matches Love2d's semantics!
// Eventually it might read from a streaming decoder of some kind,
// but for now it is just an in-memory SoundData structure.
// The source of a rodio decoder must be Send, which something
// that contains a reference to a ZipFile is not, so we are going
// to just slurp all the data into memory for now.
// There's really a lot of work that needs to be done here, since
// rodio has gotten better (if still somewhat arcane) and our filesystem
// code has done the data-slurping-from-zip's for us
// but for now it works.
pub struct Source {
    data: io::Cursor<SoundData>,
    sink: rodio::Sink,
}

impl Source {
    /// Create a new Source from the given file.
    pub fn new<P: AsRef<path::Path>>(context: &mut Context, path: P) -> GameResult<Self> {
        let path = path.as_ref();
        let data = {
            let file = &mut context.filesystem.open(path)?;
            SoundData::from_read(file)?
        };
        Source::from_data(context, data)
    }

    /// Creates a new Source using the given SoundData object.
    pub fn from_data(context: &mut Context, data: SoundData) -> GameResult<Self> {
        let sink = rodio::Sink::new(&context.audio_context.endpoint);
        let cursor = io::Cursor::new(data);
        Ok(Source {
            data: cursor,
            sink: sink,
        })
    }

    /// Plays the Source.
    pub fn play(&self) -> GameResult<()> {
        // Creating a new Decoder each time seems a little messy,
        // since it may do checking and data-type detection that is
        // redundant, but it's not super expensive.
        // See https://github.com/ggez/ggez/issues/98 for discussion
        let cursor = self.data.clone();
        let decoder = rodio::Decoder::new(cursor)?;
        self.sink.append(decoder);
        Ok(())
    }

    /// Pauses playback
    pub fn pause(&self) {
        self.sink.pause()
    }

    /// Resumes playback
    pub fn resume(&self) {
        self.sink.play()
    }

    /// Stops playback
    pub fn stop(&self) {
        self.sink.stop()
    }

    /// Gets the current volume
    pub fn volume(&self) -> f32 {
        self.sink.volume()
    }

    /// Sets the current volume
    pub fn set_volume(&mut self, value: f32) {
        self.sink.set_volume(value)
    }

    /// Get whether or not the source is paused
    pub fn paused(&self) -> bool {
        self.sink.is_paused()
    }

    /// Get whether or not the source is playing
    pub fn playing(&self) -> bool {
        !self.paused() // && !self.stopped()
    }
}

impl fmt::Debug for Source {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<Audio source: {:p}>", self)
    }
}

// TODO: global start, stop, volume?
<|endoftext|>


<commit_before>// Copyright (c) 2013-2104 Michael Dvorkin
// Ante is an esoteric programming language where all you've got is a deck of cards.
//
// This is Ante implementation in Rust.

extern crate regex;
extern crate num;

use std::io::File;
use std::collections::HashMap;

use regex::Regex;
use num::bigint::BigInt;

struct Card {
	rank: u32,
	suit: u32
}

struct Ante {
	pc:     int,                    // Program counter (index within ante.code)
	line:   int,                    // Current line number.
    code:   Vec<Card>,              // Array of cards.
    vars:   HashMap<char, uint>,    // Four registers hashed by suit.
    labels: HashMap<uint, uint>,    // Labels for ante.pc to jump to.
    buffer: Vec<char>               // Buffer to collect UTF-8 character bytes.
}

impl Ante {
    fn new() -> Ante {
        let mut vars = HashMap::new();
        vars.insert('♦', 0);
        vars.insert('♥', 0);
        vars.insert('♠', 0);
        vars.insert('♣', 0);

        Ante {
            pc:     0,
            line:   0,
            code:   vec![],
            vars:   vars,
            labels: HashMap::new(),
            buffer: vec![]
        }
    }

    fn run(& mut self, filename: &str) {
        let mut file = File::open(&Path::new(filename));
        let program = file.read_to_string().unwrap();
        println!("file: {}", program);
    }
}

fn main() {
    println!("usage: ante filename.ante");
    Ante::new().run("hello.ante".as_slice());
}
<commit_msg>Split program blob into lines getting rid of comments and whitespaces<commit_after>// Copyright (c) 2013-2104 Michael Dvorkin
// Ante is an esoteric programming language where all you've got is a deck of cards.
//
// This is Ante implementation in Rust.

extern crate regex;
extern crate num;

use std::io::File;
use std::collections::HashMap;

use regex::Regex;
use num::bigint::BigInt;

struct Card {
    rank: u32,
    suit: u32
}

struct Ante {
    pc:     int,                    // Program counter (index within ante.code)
    line:   int,                    // Current line number.
    code:   Vec<Card>,              // Array of cards.
    vars:   HashMap<char, uint>,    // Four registers hashed by suit.
    labels: HashMap<uint, uint>,    // Labels for ante.pc to jump to.
    buffer: Vec<char>               // Buffer to collect UTF-8 character bytes.
}

impl Ante {
    fn new() -> Ante {
        let mut vars = HashMap::new();
        vars.insert('♦', 0);
        vars.insert('♥', 0);
        vars.insert('♠', 0);
        vars.insert('♣', 0);

        Ante {
            pc:     0,
            line:   0,
            code:   vec![],
            vars:   vars,
            labels: HashMap::new(),
            buffer: vec![]
        }
    }

    fn run(&mut self, filename: &str) {
        let mut file = File::open(&Path::new(filename));
        let program = file.read_to_string().unwrap();
        println!("file: {}", program);
        self.parse(program.as_slice())
    }

    // Turn source file into array of cards.
    fn parse(&mut self, program: &str) {
        // Split program blob into lines getting rid of comments and whitespaces.
        let comments = Regex::new(r"#.*$").unwrap();
        let lines: Vec<String> = program.lines().map( |line|
            comments.replace_all(line, "").as_slice().trim().to_string()
        ).collect();
    }
}

fn main() {
    println!("usage: ante filename.ante");
    Ante::new().run("hello.ante".as_slice());
}
<|endoftext|>


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

/*!
# Translation of inline assembly.
*/

use core::prelude::*;

use lib;
use middle::trans::build::*;
use middle::trans::callee;
use middle::trans::common::*;
use middle::ty;

use syntax::ast;

// Take an inline assembly expression and splat it out via LLVM
pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {

    let mut bcx = bcx;
    let mut constraints = ~[];
    let mut cleanups = ~[];
    let mut aoutputs = ~[];

    // Prepare the output operands
    let outputs = do ia.outputs.map |&(c, out)| {
        constraints.push(copy *c);

        let aoutty = ty::arg {
            mode: ast::expl(ast::by_copy),
            ty: expr_ty(bcx, out)
        };
        aoutputs.push(unpack_result!(bcx, {
            callee::trans_arg_expr(bcx, aoutty, out, &mut cleanups, None, callee::DontAutorefArg)
        }));

        let e = match out.node {
            ast::expr_addr_of(_, e) => e,
            _ => fail!(~"Expression must be addr of")
        };

        let outty = ty::arg {
            mode: ast::expl(ast::by_copy),
            ty: expr_ty(bcx, e)
        };

        unpack_result!(bcx, {
            callee::trans_arg_expr(bcx, outty, e, &mut cleanups, None, callee::DontAutorefArg)
        })

    };

    for cleanups.each |c| {
        revoke_clean(bcx, *c);
    }
    cleanups.clear();

    // Now the input operands
    let inputs = do ia.inputs.map |&(c, in)| {
        constraints.push(copy *c);

        let inty = ty::arg {
            mode: ast::expl(ast::by_copy),
            ty: expr_ty(bcx, in)
        };

        unpack_result!(bcx, {
            callee::trans_arg_expr(bcx, inty, in, &mut cleanups, None, callee::DontAutorefArg)
        })

    };

    for cleanups.each |c| {
        revoke_clean(bcx, *c);
    }

    let mut constraints = str::connect(constraints, ",");

    let mut clobbers = getClobbers();
    if *ia.clobbers != ~"" && clobbers != ~"" {
        clobbers = *ia.clobbers + ~"," + clobbers;
    } else {
        clobbers += *ia.clobbers;
    };

    // Add the clobbers to our constraints list
    if clobbers != ~"" && constraints != ~"" {
        constraints += ~"," + clobbers;
    } else {
        constraints += clobbers;
    }

    debug!("Asm Constraints: %?", constraints);

    let numOutputs = outputs.len();

    // Depending on how many outputs we have, the return type is different
    let output = if numOutputs == 0 {
        T_void()
    } else if numOutputs == 1 {
        val_ty(outputs[0])
    } else {
        T_struct(outputs.map(|o| val_ty(*o)))
    };

    let dialect = match ia.dialect {
        ast::asm_att   => lib::llvm::AD_ATT,
        ast::asm_intel => lib::llvm::AD_Intel
    };

    let r = do str::as_c_str(*ia.asm) |a| {
        do str::as_c_str(constraints) |c| {
            // XXX: Allow selection of at&t or intel
            InlineAsmCall(bcx, a, c, inputs, output, ia.volatile, ia.alignstack, dialect)
        }
    };

    // Again, based on how many outputs we have
    if numOutputs == 1 {
        let op = PointerCast(bcx, aoutputs[0], T_ptr(val_ty(outputs[0])));
        Store(bcx, r, op);
    } else {
        for aoutputs.eachi |i, o| {
            let v = ExtractValue(bcx, r, i);
            let op = PointerCast(bcx, *o, T_ptr(val_ty(outputs[i])));
            Store(bcx, v, op);
        }
    }

    return bcx;

}

// Default per-arch clobbers
// Basically what clang does

#[cfg(target_arch = "arm")]
#[cfg(target_arch = "mips")]
fn getClobbers() -> ~str {
    ~""
}

#[cfg(target_arch = "x86")]
#[cfg(target_arch = "x86_64")]
fn getClobbers() -> ~str {
    ~"~{dirflag},~{fpsr},~{flags}"
}
<commit_msg>librustc: remove already addressed XXX<commit_after>// Copyright 2012 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.

/*!
# Translation of inline assembly.
*/

use core::prelude::*;

use lib;
use middle::trans::build::*;
use middle::trans::callee;
use middle::trans::common::*;
use middle::ty;

use syntax::ast;

// Take an inline assembly expression and splat it out via LLVM
pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {

    let mut bcx = bcx;
    let mut constraints = ~[];
    let mut cleanups = ~[];
    let mut aoutputs = ~[];

    // Prepare the output operands
    let outputs = do ia.outputs.map |&(c, out)| {
        constraints.push(copy *c);

        let aoutty = ty::arg {
            mode: ast::expl(ast::by_copy),
            ty: expr_ty(bcx, out)
        };
        aoutputs.push(unpack_result!(bcx, {
            callee::trans_arg_expr(bcx, aoutty, out, &mut cleanups, None, callee::DontAutorefArg)
        }));

        let e = match out.node {
            ast::expr_addr_of(_, e) => e,
            _ => fail!(~"Expression must be addr of")
        };

        let outty = ty::arg {
            mode: ast::expl(ast::by_copy),
            ty: expr_ty(bcx, e)
        };

        unpack_result!(bcx, {
            callee::trans_arg_expr(bcx, outty, e, &mut cleanups, None, callee::DontAutorefArg)
        })

    };

    for cleanups.each |c| {
        revoke_clean(bcx, *c);
    }
    cleanups.clear();

    // Now the input operands
    let inputs = do ia.inputs.map |&(c, in)| {
        constraints.push(copy *c);

        let inty = ty::arg {
            mode: ast::expl(ast::by_copy),
            ty: expr_ty(bcx, in)
        };

        unpack_result!(bcx, {
            callee::trans_arg_expr(bcx, inty, in, &mut cleanups, None, callee::DontAutorefArg)
        })

    };

    for cleanups.each |c| {
        revoke_clean(bcx, *c);
    }

    let mut constraints = str::connect(constraints, ",");

    let mut clobbers = getClobbers();
    if *ia.clobbers != ~"" && clobbers != ~"" {
        clobbers = *ia.clobbers + ~"," + clobbers;
    } else {
        clobbers += *ia.clobbers;
    };

    // Add the clobbers to our constraints list
    if clobbers != ~"" && constraints != ~"" {
        constraints += ~"," + clobbers;
    } else {
        constraints += clobbers;
    }

    debug!("Asm Constraints: %?", constraints);

    let numOutputs = outputs.len();

    // Depending on how many outputs we have, the return type is different
    let output = if numOutputs == 0 {
        T_void()
    } else if numOutputs == 1 {
        val_ty(outputs[0])
    } else {
        T_struct(outputs.map(|o| val_ty(*o)))
    };

    let dialect = match ia.dialect {
        ast::asm_att   => lib::llvm::AD_ATT,
        ast::asm_intel => lib::llvm::AD_Intel
    };

    let r = do str::as_c_str(*ia.asm) |a| {
        do str::as_c_str(constraints) |c| {
            InlineAsmCall(bcx, a, c, inputs, output, ia.volatile, ia.alignstack, dialect)
        }
    };

    // Again, based on how many outputs we have
    if numOutputs == 1 {
        let op = PointerCast(bcx, aoutputs[0], T_ptr(val_ty(outputs[0])));
        Store(bcx, r, op);
    } else {
        for aoutputs.eachi |i, o| {
            let v = ExtractValue(bcx, r, i);
            let op = PointerCast(bcx, *o, T_ptr(val_ty(outputs[i])));
            Store(bcx, v, op);
        }
    }

    return bcx;

}

// Default per-arch clobbers
// Basically what clang does

#[cfg(target_arch = "arm")]
#[cfg(target_arch = "mips")]
fn getClobbers() -> ~str {
    ~""
}

#[cfg(target_arch = "x86")]
#[cfg(target_arch = "x86_64")]
fn getClobbers() -> ~str {
    ~"~{dirflag},~{fpsr},~{flags}"
}
<|endoftext|>