<commit_before>//! # Diesel
//!
//! Diesel is an ORM and query builder designed to reduce the boilerplate for database interactions.
//! If this is your first time reading this documentation,
//! we recommend you start with the [getting started guide].
//! We also have [many other long form guides].
//!
//! [getting started guide]: https://diesel.rs/guides/getting-started/
//! [many other long form guides]: https://diesel.rs/guides
//!
//! # Where to find things
//!
//! ## Declaring your schema
//!
//! So Diesel is able to validate your queries at compile time,
//! it requires you to specify your schema in your code,
//! which you can do with [the `table!` macro][`table!`].
//! `diesel print-schema` or `infer_schema!` can be used
//! to automatically generate these macro calls
//! (by connecting to your database and querying its schema).
//!
//! [`table!`]: macro.table.html
//!
//! ## Getting started
//!
//! Queries usually start from either a table, or a function like [`update`].
//! Those functions can be found [here](#functions).
//!
//! Diesel provides a [`prelude` module](prelude),
//! which exports most of the typically used traits and types.
//! We are conservative about what goes in this module,
//! and avoid anything which has a generic name.
//! Files which use Diesel are expected to have `use diesel::prelude::*;`.
//!
//! [`update`]: fn.update.html
//!
//! ## Constructing a query
//!
//! The tools the query builder gives you can be put into these three categories:
//!
//! - "Query builder methods" are things that map to portions of a whole query
//!   (such as `ORDER` and `WHERE`). These methods usually have the same name
//!   as the SQL they map to, except for `WHERE` which is called `filter` in Diesel
//!   (To not conflict with the Rust keyword).
//!   These methods live in [the `query_dsl` module](query_dsl).
//! - "Expression methods" are things you would call on columns
//!   or other individual values.
//!   These methods live in [the `expression_methods` module](expression_methods)
//!   You can often find these by thinking "what would this be called"
//!   if it were a method
//!   and typing that into the search bar
//!   (e.g. `LIKE` is called `like` in Diesel).
//!   Most operators are named based on the Rust function which maps to that
//!   operator in [`std::ops`]
//!   (For example `==` is called `.eq`, and `!=` is called `.ne`).
//! - "Bare functions" are normal SQL functions
//!   such as `sum`.
//!   They live in [the `dsl` module](dsl).
//!   Diesel only supports a very small number of these functions.
//!   You can declare additional functions you want to use
//!   with [the `sql_function!` macro][`sql_function!`].
//!
//! [`std::ops`]: //doc.rust-lang.org/stable/std/ops/index.html
//! [`sql_function!`]: macro.sql_function.html
//!
//! ## Serializing and Deserializing
//!
//! Types which represent the result of a SQL query implement
//! a trait called [`Queryable`].
//!
//! Diesel maps "Rust types" (e.g. `i32`) to and from "SQL types"
//! (e.g. [`diesel::types::Integer`]).
//! You can find all the types supported by Diesel in [the `types` module](types).
//! These types are only used to represent a SQL type.
//! You should never put them on your `Queryable` structs.
//!
//! To find all the Rust types which can be used with a given SQL type,
//! see the documentation for that SQL type.
//!
//! To find all the SQL types which can be used with a Rust type,
//! go to the docs for either [`ToSql`] or [`FromSql`],
//! go to the "Implementors" section,
//! and find the Rust type you want to use.
//!
//! [`Queryable`]: query_source/trait.Queryable.html
//! [`diesel::types::Integer`]: types/struct.Integer.html
//! [`ToSql`]: types/trait.ToSql.html
//! [`FromSql`]: types/trait.FromSql.html
//!
//! ## Getting help
//!
//! If you run into problems, Diesel has a very active Gitter room.
//! You can come ask for help at
//! [gitter.im/diesel-rs/diesel](https://gitter.im/diesel-rs/diesel)

#![cfg_attr(feature = "unstable", feature(specialization))]
// Built-in Lints
#![deny(warnings, missing_debug_implementations, missing_copy_implementations)]
// Clippy lints
#![cfg_attr(feature = "clippy", allow(unstable_features))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
#![cfg_attr(feature = "clippy",
            allow(option_map_unwrap_or_else, option_map_unwrap_or, match_same_arms,
                  type_complexity))]
#![cfg_attr(feature = "clippy",
            warn(option_unwrap_used, result_unwrap_used, print_stdout,
                 wrong_pub_self_convention, mut_mut, non_ascii_literal, similar_names,
                 unicode_not_nfc, enum_glob_use, if_not_else, items_after_statements,
                 used_underscore_binding))]
#![cfg_attr(all(test, feature = "clippy"), allow(option_unwrap_used, result_unwrap_used))]

#[cfg(feature = "postgres")]
#[macro_use]
extern crate bitflags;
extern crate byteorder;
// This is required to make `diesel_derives` re-export, but clippy thinks its unused
#[cfg_attr(feature = "clippy", allow(useless_attribute))]
#[allow(unused_imports)]
#[macro_use]
extern crate diesel_derives;
#[doc(hidden)]
pub use diesel_derives::*;

#[macro_use]
mod macros;

#[cfg(test)]
#[macro_use]
extern crate cfg_if;

#[cfg(test)]
pub mod test_helpers;

#[deny(missing_docs)]
pub mod associations;
#[deny(missing_docs)]
pub mod backend;
#[doc(hidden)]
pub mod connection;
#[macro_use]
#[deny(missing_docs)]
pub mod expression;
#[deny(missing_docs)]
pub mod expression_methods;
#[doc(hidden)]
pub mod insertable;
#[deny(missing_docs)]
pub mod query_builder;
#[deny(missing_docs)]
#[macro_use]
pub mod types;

#[cfg(feature = "mysql")]
#[deny(missing_docs)]
pub mod mysql;
#[cfg(feature = "postgres")]
#[deny(missing_docs)]
pub mod pg;
#[cfg(feature = "sqlite")]
#[deny(missing_docs)]
pub mod sqlite;

#[deny(missing_docs)]
pub mod query_dsl;
#[deny(missing_docs)]
pub mod query_source;
#[deny(missing_docs)]
pub mod result;
#[deny(missing_docs)]
pub mod row;
mod util;

pub mod dsl {
    //! Includes various helper types and bare functions which are named too
    //! generically to be included in prelude, but are often used when using Diesel.

    #[doc(inline)]
    pub use helper_types::*;

    #[doc(inline)]
    pub use expression::dsl::*;
}

pub mod helper_types {
    //! Provide helper types for concisely writing the return type of functions.
    //! As with iterators, it is unfortunately difficult to return a partially
    //! constructed query without exposing the exact implementation of the
    //! function. Without higher kinded types, these various DSLs can't be
    //! combined into a single trait for boxing purposes.
    //!
    //! All types here are in the form `<FirstType as
    //! DslName<OtherTypes>>::Output`. So the return type of
    //! `users.filter(first_name.eq("John")).order(last_name.asc()).limit(10)` would
    //! be `Limit<Order<FindBy<users, first_name, &str>, Asc<last_name>>>`
    use super::query_dsl::*;
    use super::query_dsl::methods::*;
    use super::query_source::joins;

    #[doc(inline)]
    pub use expression::helper_types::*;

    /// Represents the return type of `.select(selection)`
    pub type Select<Source, Selection> = <Source as SelectDsl<Selection>>::Output;

    /// Represents the return type of `.filter(predicate)`
    pub type Filter<Source, Predicate> = <Source as FilterDsl<Predicate>>::Output;

    /// Represents the return type of `.filter(lhs.eq(rhs))`
    pub type FindBy<Source, Column, Value> = Filter<Source, Eq<Column, Value>>;

    /// Represents the return type of `.for_update()`
    pub type ForUpdate<Source> = <Source as ForUpdateDsl>::Output;

    /// Represents the return type of `.find(pk)`
    pub type Find<Source, PK> = <Source as FindDsl<PK>>::Output;

    /// Represents the return type of `.order(ordering)`
    pub type Order<Source, Ordering> = <Source as OrderDsl<Ordering>>::Output;

    /// Represents the return type of `.limit()`
    pub type Limit<Source> = <Source as LimitDsl>::Output;

    /// Represents the return type of `.offset()`
    pub type Offset<Source> = <Source as OffsetDsl>::Output;

    /// Represents the return type of `.inner_join(rhs)`
    pub type InnerJoin<Source, Rhs> =
        <Source as JoinWithImplicitOnClause<Rhs, joins::Inner>>::Output;

    /// Represents the return type of `.left_join(rhs)`
    pub type LeftJoin<Source, Rhs> =
        <Source as JoinWithImplicitOnClause<Rhs, joins::LeftOuter>>::Output;

    use super::associations::HasTable;
    use super::query_builder::{AsChangeset, IntoUpdateTarget, UpdateStatement};
    /// Represents the return type of `update(lhs).set(rhs)`
    pub type Update<Target, Changes> = UpdateStatement<
        <Target as HasTable>::Table,
        <Target as IntoUpdateTarget>::WhereClause,
        <Changes as AsChangeset>::Changeset,
    >;

    /// Represents the return type of `.into_boxed::<'a, DB>()`
    pub type IntoBoxed<'a, Source, DB> = <Source as BoxedDsl<'a, DB>>::Output;

    /// Represents the return type of `.distinct()`
    pub type Distinct<Source> = <Source as DistinctDsl>::Output;

    /// Represents the return type of `.distinct_on(expr)`
    #[cfg(feature = "postgres")]
    pub type DistinctOn<Source, Expr> = <Source as DistinctOnDsl<Expr>>::Output;
}

pub mod prelude {
    //! Re-exports important traits and types. Meant to be glob imported when using Diesel.
    pub use associations::{GroupedBy, Identifiable};
    pub use connection::Connection;
    pub use expression::{AppearsOnTable, BoxableExpression, Expression, IntoSql,
                         SelectableExpression};
    pub use expression_methods::*;
    #[doc(inline)]
    pub use insertable::Insertable;
    #[doc(hidden)]
    pub use query_dsl::GroupByDsl;
    pub use query_dsl::{BelongingToDsl, JoinOnDsl, QueryDsl, RunQueryDsl, SaveChangesDsl};

    pub use query_source::{Column, JoinTo, QuerySource, Queryable, Table};
    pub use result::{ConnectionError, ConnectionResult, OptionalExtension, QueryResult};

    #[cfg(feature = "postgres")]
    pub use pg::PgConnection;
    #[cfg(feature = "sqlite")]
    pub use sqlite::SqliteConnection;
    #[cfg(feature = "mysql")]
    pub use mysql::MysqlConnection;
}

pub use prelude::*;
#[doc(inline)]
pub use query_builder::debug_query;
#[doc(inline)]
pub use query_builder::functions::{delete, insert_into, replace_into, select, sql_query, update};
pub use result::Error::NotFound;
#[doc(inline)]
pub use types::structs::data_types;
<commit_msg>Docs 🎉<commit_after>//! # Diesel
//!
//! Diesel is an ORM and query builder designed to reduce the boilerplate for database interactions.
//! If this is your first time reading this documentation,
//! we recommend you start with the [getting started guide].
//! We also have [many other long form guides].
//!
//! [getting started guide]: https://diesel.rs/guides/getting-started/
//! [many other long form guides]: https://diesel.rs/guides
//!
//! # Where to find things
//!
//! ## Declaring your schema
//!
//! So Diesel is able to validate your queries at compile time,
//! it requires you to specify your schema in your code,
//! which you can do with [the `table!` macro][`table!`].
//! `diesel print-schema` or `infer_schema!` can be used
//! to automatically generate these macro calls
//! (by connecting to your database and querying its schema).
//!
//! [`table!`]: macro.table.html
//!
//! ## Getting started
//!
//! Queries usually start from either a table, or a function like [`update`].
//! Those functions can be found [here](#functions).
//!
//! Diesel provides a [`prelude` module](prelude),
//! which exports most of the typically used traits and types.
//! We are conservative about what goes in this module,
//! and avoid anything which has a generic name.
//! Files which use Diesel are expected to have `use diesel::prelude::*;`.
//!
//! [`update`]: fn.update.html
//!
//! ## Constructing a query
//!
//! The tools the query builder gives you can be put into these three categories:
//!
//! - "Query builder methods" are things that map to portions of a whole query
//!   (such as `ORDER` and `WHERE`). These methods usually have the same name
//!   as the SQL they map to, except for `WHERE` which is called `filter` in Diesel
//!   (To not conflict with the Rust keyword).
//!   These methods live in [the `query_dsl` module](query_dsl).
//! - "Expression methods" are things you would call on columns
//!   or other individual values.
//!   These methods live in [the `expression_methods` module](expression_methods)
//!   You can often find these by thinking "what would this be called"
//!   if it were a method
//!   and typing that into the search bar
//!   (e.g. `LIKE` is called `like` in Diesel).
//!   Most operators are named based on the Rust function which maps to that
//!   operator in [`std::ops`]
//!   (For example `==` is called `.eq`, and `!=` is called `.ne`).
//! - "Bare functions" are normal SQL functions
//!   such as `sum`.
//!   They live in [the `dsl` module](dsl).
//!   Diesel only supports a very small number of these functions.
//!   You can declare additional functions you want to use
//!   with [the `sql_function!` macro][`sql_function!`].
//!
//! [`std::ops`]: //doc.rust-lang.org/stable/std/ops/index.html
//! [`sql_function!`]: macro.sql_function.html
//!
//! ## Serializing and Deserializing
//!
//! Types which represent the result of a SQL query implement
//! a trait called [`Queryable`].
//!
//! Diesel maps "Rust types" (e.g. `i32`) to and from "SQL types"
//! (e.g. [`diesel::types::Integer`]).
//! You can find all the types supported by Diesel in [the `types` module](types).
//! These types are only used to represent a SQL type.
//! You should never put them on your `Queryable` structs.
//!
//! To find all the Rust types which can be used with a given SQL type,
//! see the documentation for that SQL type.
//!
//! To find all the SQL types which can be used with a Rust type,
//! go to the docs for either [`ToSql`] or [`FromSql`],
//! go to the "Implementors" section,
//! and find the Rust type you want to use.
//!
//! [`Queryable`]: query_source/trait.Queryable.html
//! [`diesel::types::Integer`]: types/struct.Integer.html
//! [`ToSql`]: types/trait.ToSql.html
//! [`FromSql`]: types/trait.FromSql.html
//!
//! ## Getting help
//!
//! If you run into problems, Diesel has a very active Gitter room.
//! You can come ask for help at
//! [gitter.im/diesel-rs/diesel](https://gitter.im/diesel-rs/diesel)

#![cfg_attr(feature = "unstable", feature(specialization))]
// Built-in Lints
#![deny(warnings, missing_debug_implementations, missing_copy_implementations, missing_docs)]
// Clippy lints
#![cfg_attr(feature = "clippy", allow(unstable_features))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
#![cfg_attr(feature = "clippy",
            allow(option_map_unwrap_or_else, option_map_unwrap_or, match_same_arms,
                  type_complexity))]
#![cfg_attr(feature = "clippy",
            warn(option_unwrap_used, result_unwrap_used, print_stdout,
                 wrong_pub_self_convention, mut_mut, non_ascii_literal, similar_names,
                 unicode_not_nfc, enum_glob_use, if_not_else, items_after_statements,
                 used_underscore_binding))]
#![cfg_attr(all(test, feature = "clippy"), allow(option_unwrap_used, result_unwrap_used))]

#[cfg(feature = "postgres")]
#[macro_use]
extern crate bitflags;
extern crate byteorder;
// This is required to make `diesel_derives` re-export, but clippy thinks its unused
#[cfg_attr(feature = "clippy", allow(useless_attribute))]
#[allow(unused_imports)]
#[macro_use]
extern crate diesel_derives;
#[doc(hidden)]
pub use diesel_derives::*;

#[macro_use]
mod macros;

#[cfg(test)]
#[macro_use]
extern crate cfg_if;

#[cfg(test)]
pub mod test_helpers;

pub mod associations;
pub mod backend;
#[doc(hidden)]
pub mod connection;
#[macro_use]
pub mod expression;
pub mod expression_methods;
#[doc(hidden)]
pub mod insertable;
pub mod query_builder;
#[macro_use]
pub mod types;

#[cfg(feature = "mysql")]
pub mod mysql;
#[cfg(feature = "postgres")]
pub mod pg;
#[cfg(feature = "sqlite")]
pub mod sqlite;

pub mod query_dsl;
pub mod query_source;
pub mod result;
pub mod row;
mod util;

pub mod dsl {
    //! Includes various helper types and bare functions which are named too
    //! generically to be included in prelude, but are often used when using Diesel.

    #[doc(inline)]
    pub use helper_types::*;

    #[doc(inline)]
    pub use expression::dsl::*;
}

pub mod helper_types {
    //! Provide helper types for concisely writing the return type of functions.
    //! As with iterators, it is unfortunately difficult to return a partially
    //! constructed query without exposing the exact implementation of the
    //! function. Without higher kinded types, these various DSLs can't be
    //! combined into a single trait for boxing purposes.
    //!
    //! All types here are in the form `<FirstType as
    //! DslName<OtherTypes>>::Output`. So the return type of
    //! `users.filter(first_name.eq("John")).order(last_name.asc()).limit(10)` would
    //! be `Limit<Order<FindBy<users, first_name, &str>, Asc<last_name>>>`
    use super::query_dsl::*;
    use super::query_dsl::methods::*;
    use super::query_source::joins;

    #[doc(inline)]
    pub use expression::helper_types::*;

    /// Represents the return type of `.select(selection)`
    pub type Select<Source, Selection> = <Source as SelectDsl<Selection>>::Output;

    /// Represents the return type of `.filter(predicate)`
    pub type Filter<Source, Predicate> = <Source as FilterDsl<Predicate>>::Output;

    /// Represents the return type of `.filter(lhs.eq(rhs))`
    pub type FindBy<Source, Column, Value> = Filter<Source, Eq<Column, Value>>;

    /// Represents the return type of `.for_update()`
    pub type ForUpdate<Source> = <Source as ForUpdateDsl>::Output;

    /// Represents the return type of `.find(pk)`
    pub type Find<Source, PK> = <Source as FindDsl<PK>>::Output;

    /// Represents the return type of `.order(ordering)`
    pub type Order<Source, Ordering> = <Source as OrderDsl<Ordering>>::Output;

    /// Represents the return type of `.limit()`
    pub type Limit<Source> = <Source as LimitDsl>::Output;

    /// Represents the return type of `.offset()`
    pub type Offset<Source> = <Source as OffsetDsl>::Output;

    /// Represents the return type of `.inner_join(rhs)`
    pub type InnerJoin<Source, Rhs> =
        <Source as JoinWithImplicitOnClause<Rhs, joins::Inner>>::Output;

    /// Represents the return type of `.left_join(rhs)`
    pub type LeftJoin<Source, Rhs> =
        <Source as JoinWithImplicitOnClause<Rhs, joins::LeftOuter>>::Output;

    use super::associations::HasTable;
    use super::query_builder::{AsChangeset, IntoUpdateTarget, UpdateStatement};
    /// Represents the return type of `update(lhs).set(rhs)`
    pub type Update<Target, Changes> = UpdateStatement<
        <Target as HasTable>::Table,
        <Target as IntoUpdateTarget>::WhereClause,
        <Changes as AsChangeset>::Changeset,
    >;

    /// Represents the return type of `.into_boxed::<'a, DB>()`
    pub type IntoBoxed<'a, Source, DB> = <Source as BoxedDsl<'a, DB>>::Output;

    /// Represents the return type of `.distinct()`
    pub type Distinct<Source> = <Source as DistinctDsl>::Output;

    /// Represents the return type of `.distinct_on(expr)`
    #[cfg(feature = "postgres")]
    pub type DistinctOn<Source, Expr> = <Source as DistinctOnDsl<Expr>>::Output;
}

pub mod prelude {
    //! Re-exports important traits and types. Meant to be glob imported when using Diesel.
    pub use associations::{GroupedBy, Identifiable};
    pub use connection::Connection;
    pub use expression::{AppearsOnTable, BoxableExpression, Expression, IntoSql,
                         SelectableExpression};
    pub use expression_methods::*;
    #[doc(inline)]
    pub use insertable::Insertable;
    #[doc(hidden)]
    pub use query_dsl::GroupByDsl;
    pub use query_dsl::{BelongingToDsl, JoinOnDsl, QueryDsl, RunQueryDsl, SaveChangesDsl};

    pub use query_source::{Column, JoinTo, QuerySource, Queryable, Table};
    pub use result::{ConnectionError, ConnectionResult, OptionalExtension, QueryResult};

    #[cfg(feature = "postgres")]
    pub use pg::PgConnection;
    #[cfg(feature = "sqlite")]
    pub use sqlite::SqliteConnection;
    #[cfg(feature = "mysql")]
    pub use mysql::MysqlConnection;
}

pub use prelude::*;
#[doc(inline)]
pub use query_builder::debug_query;
#[doc(inline)]
pub use query_builder::functions::{delete, insert_into, replace_into, select, sql_query, update};
pub use result::Error::NotFound;
#[doc(inline)]
pub use types::structs::data_types;
<|endoftext|>


<commit_before>use rusqlite::{TransactionBehavior, Connection, DropBehavior, Result};
use std::ops::Deref;

/// Represents a transaction on a database connection.
///
/// ## Note
///
/// Transactions will roll back by default. Use `commit` method to explicitly commit the
/// transaction, or use `set_drop_behavior` to change what happens when the transaction
/// is dropped.
///
/// ## Example
///
/// ```rust,no_run
/// # use rusqlite::{Connection, Result};
/// # fn do_queries_part_1(_conn: &Connection) -> Result<()> { Ok(()) }
/// # fn do_queries_part_2(_conn: &Connection) -> Result<()> { Ok(()) }
/// fn perform_queries(conn: &mut Connection) -> Result<()> {
///     let tx = try!(conn.transaction());
///
///     try!(do_queries_part_1(&tx)); // tx causes rollback if this fails
///     try!(do_queries_part_2(&tx)); // tx causes rollback if this fails
///
///     tx.commit()
/// }
/// ```
pub struct Transaction<'conn> {
    conn: &'conn Connection,
    drop_behavior: DropBehavior,
    committed: bool,
}

impl<'conn> Transaction<'conn> {
    /// Begin a new transaction. Cannot be nested; see `savepoint` for nested transactions.
    pub fn new(conn: &Connection, behavior: TransactionBehavior) -> Result<Transaction> {
        let query = match behavior {
            TransactionBehavior::Deferred => "BEGIN DEFERRED",
            TransactionBehavior::Immediate => "BEGIN IMMEDIATE",
            TransactionBehavior::Exclusive => "BEGIN EXCLUSIVE",
        };
        conn.execute_batch(query)
            .map(move |_| {
                Transaction {
                    conn: conn,
                    drop_behavior: DropBehavior::Rollback,
                    committed: false,
                }
            })
    }

    /// A convenience method which consumes and commits a transaction.
    pub fn commit(mut self) -> Result<()> {
        self.commit_()
    }

    fn commit_(&mut self) -> Result<()> {
        self.committed = true;
        self.conn.execute_batch("COMMIT")
    }
}

impl<'conn> Deref for Transaction<'conn> {
    type Target = Connection;

    fn deref(&self) -> &Connection {
        self.conn
    }
}<commit_msg>Fix code style<commit_after>use rusqlite::{TransactionBehavior, Connection, DropBehavior, Result};
use std::ops::Deref;

pub struct Transaction<'conn> {
    conn: &'conn Connection,
    drop_behavior: DropBehavior,
    committed: bool,
}

impl<'conn> Transaction<'conn> {
    /// Begin a new transaction. Cannot be nested; see `savepoint` for nested transactions.
    pub fn new(conn: &Connection, behavior: TransactionBehavior) -> Result<Transaction> {
        let query = match behavior {
            TransactionBehavior::Deferred => "BEGIN DEFERRED",
            TransactionBehavior::Immediate => "BEGIN IMMEDIATE",
            TransactionBehavior::Exclusive => "BEGIN EXCLUSIVE",
        };
        conn.execute_batch(query)
            .map(move |_| {
                Transaction {
                    conn,
                    drop_behavior: DropBehavior::Rollback,
                    committed: false,
                }
            })
    }

    /// A convenience method which consumes and commits a transaction.
    pub fn commit(mut self) -> Result<()> {
        self.commit_()
    }

    fn commit_(&mut self) -> Result<()> {
        self.committed = true;
        self.conn.execute_batch("COMMIT")
    }
}

impl<'conn> Deref for Transaction<'conn> {
    type Target = Connection;

    fn deref(&self) -> &Connection {
        self.conn
    }
}<|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.

use hir::def_id::DefId;
use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
use ty::subst::{Kind, Subst};
use traits;
use syntax::abi::Abi;
use syntax::codemap::DUMMY_SP;
use util::ppaux;

use std::fmt;

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct Instance<'tcx> {
    pub def: InstanceDef<'tcx>,
    pub substs: &'tcx Substs<'tcx>,
}

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum InstanceDef<'tcx> {
    Item(DefId),
    Intrinsic(DefId),

    /// <fn() as FnTrait>::call_*
    /// def-id is FnTrait::call_*
    FnPtrShim(DefId, Ty<'tcx>),

    /// <Trait as Trait>::fn
    Virtual(DefId, usize),

    /// <[mut closure] as FnOnce>::call_once
    ClosureOnceShim { call_once: DefId },

    /// drop_in_place::<T>; None for empty drop glue.
    DropGlue(DefId, Option<Ty<'tcx>>),

    ///`<T as Clone>::clone` shim.
    CloneShim(DefId, Ty<'tcx>),
}

impl<'tcx> InstanceDef<'tcx> {
    #[inline]
    pub fn def_id(&self) -> DefId {
        match *self {
            InstanceDef::Item(def_id) |
            InstanceDef::FnPtrShim(def_id, _) |
            InstanceDef::Virtual(def_id, _) |
            InstanceDef::Intrinsic(def_id, ) |
            InstanceDef::ClosureOnceShim { call_once: def_id } |
            InstanceDef::DropGlue(def_id, _) |
            InstanceDef::CloneShim(def_id, _) => def_id
        }
    }

    #[inline]
    pub fn def_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
        tcx.type_of(self.def_id())
    }

    #[inline]
    pub fn attrs<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::Attributes<'tcx> {
        tcx.get_attrs(self.def_id())
    }
}

impl<'tcx> fmt::Display for Instance<'tcx> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        ppaux::parameterized(f, self.substs, self.def_id(), &[])?;
        match self.def {
            InstanceDef::Item(_) => Ok(()),
            InstanceDef::Intrinsic(_) => {
                write!(f, " - intrinsic")
            }
            InstanceDef::Virtual(_, num) => {
                write!(f, " - shim(#{})", num)
            }
            InstanceDef::FnPtrShim(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
            InstanceDef::ClosureOnceShim { .. } => {
                write!(f, " - shim")
            }
            InstanceDef::DropGlue(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
            InstanceDef::CloneShim(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
        }
    }
}

impl<'a, 'b, 'tcx> Instance<'tcx> {
    pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
               -> Instance<'tcx> {
        assert!(substs.is_normalized_for_trans() && !substs.has_escaping_regions(),
                "substs of instance {:?} not normalized for trans: {:?}",
                def_id, substs);
        Instance { def: InstanceDef::Item(def_id), substs: substs }
    }

    pub fn mono(tcx: TyCtxt<'a, 'tcx, 'b>, def_id: DefId) -> Instance<'tcx> {
        Instance::new(def_id, tcx.global_tcx().empty_substs_for_def_id(def_id))
    }

    #[inline]
    pub fn def_id(&self) -> DefId {
        self.def.def_id()
    }

    /// Resolve a (def_id, substs) pair to an (optional) instance -- most commonly,
    /// this is used to find the precise code that will run for a trait method invocation,
    /// if known.
    ///
    /// Returns `None` if we cannot resolve `Instance` to a specific instance.
    /// For example, in a context like this,
    ///
    /// ```
    /// fn foo<T: Debug>(t: T) { ... }
    /// ```
    ///
    /// trying to resolve `Debug::fmt` applied to `T` will yield `None`, because we do not
    /// know what code ought to run. (Note that this setting is also affected by the
    /// `RevealMode` in the parameter environment.)
    ///
    /// Presuming that coherence and type-check have succeeded, if this method is invoked
    /// in a monomorphic context (i.e., like during trans), then it is guaranteed to return
    /// `Some`.
    pub fn resolve(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                   param_env: ty::ParamEnv<'tcx>,
                   def_id: DefId,
                   substs: &'tcx Substs<'tcx>) -> Option<Instance<'tcx>> {
        debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
        let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) {
            debug!(" => associated item, attempting to find impl");
            let item = tcx.associated_item(def_id);
            resolve_associated_item(tcx, &item, param_env, trait_def_id, substs)
        } else {
            let ty = tcx.type_of(def_id);
            let item_type = tcx.trans_apply_param_substs(substs, &ty);

            let def = match item_type.sty {
                ty::TyFnDef(..) if {
                    let f = item_type.fn_sig(tcx);
                    f.abi() == Abi::RustIntrinsic ||
                        f.abi() == Abi::PlatformIntrinsic
                } =>
                {
                    debug!(" => intrinsic");
                    ty::InstanceDef::Intrinsic(def_id)
                }
                _ => {
                    if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
                        let ty = substs.type_at(0);
                        if ty.needs_drop(tcx, ty::ParamEnv::empty(traits::Reveal::All)) {
                            debug!(" => nontrivial drop glue");
                            ty::InstanceDef::DropGlue(def_id, Some(ty))
                        } else {
                            debug!(" => trivial drop glue");
                            ty::InstanceDef::DropGlue(def_id, None)
                        }
                    } else {
                        debug!(" => free item");
                        ty::InstanceDef::Item(def_id)
                    }
                }
            };
            Some(Instance {
                def: def,
                substs: substs
            })
        };
        debug!("resolve(def_id={:?}, substs={:?}) = {:?}", def_id, substs, result);
        result
    }
}

fn resolve_closure<'a, 'tcx>(
                   tcx: TyCtxt<'a, 'tcx, 'tcx>,
                   def_id: DefId,
                   substs: ty::ClosureSubsts<'tcx>,
                   requested_kind: ty::ClosureKind)
-> Instance<'tcx>
{
    let actual_kind = tcx.closure_kind(def_id);

    match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
        Ok(true) => fn_once_adapter_instance(tcx, def_id, substs),
        _ => Instance::new(def_id, substs.substs)
    }
}

fn resolve_associated_item<'a, 'tcx>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    trait_item: &ty::AssociatedItem,
    param_env: ty::ParamEnv<'tcx>,
    trait_id: DefId,
    rcvr_substs: &'tcx Substs<'tcx>
    ) -> Option<Instance<'tcx>> {
    let def_id = trait_item.def_id;
    debug!("resolve_associated_item(trait_item={:?}, \
                                    trait_id={:?}, \
           rcvr_substs={:?})",
           def_id, trait_id, rcvr_substs);

    let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
    let vtbl = tcx.trans_fulfill_obligation(DUMMY_SP, param_env, ty::Binder(trait_ref));

    // Now that we know which impl is being used, we can dispatch to
    // the actual function:
    match vtbl {
        traits::VtableImpl(impl_data) => {
            let (def_id, substs) = traits::find_associated_item(
                tcx, trait_item, rcvr_substs, &impl_data);
            let substs = tcx.erase_regions(&substs);
            Some(ty::Instance::new(def_id, substs))
        }
        traits::VtableGenerator(closure_data) => {
            Some(Instance {
                def: ty::InstanceDef::Item(closure_data.closure_def_id),
                substs: closure_data.substs.substs
            })
        }
        traits::VtableClosure(closure_data) => {
            let trait_closure_kind = tcx.lang_items().fn_trait_kind(trait_id).unwrap();
            Some(resolve_closure(tcx, closure_data.closure_def_id, closure_data.substs,
                                 trait_closure_kind))
        }
        traits::VtableFnPointer(ref data) => {
            Some(Instance {
                def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
                substs: rcvr_substs
            })
        }
        traits::VtableObject(ref data) => {
            let index = tcx.get_vtable_index_of_object_method(data, def_id);
            Some(Instance {
                def: ty::InstanceDef::Virtual(def_id, index),
                substs: rcvr_substs
            })
        }
        traits::VtableBuiltin(..) if Some(trait_id) == tcx.lang_items().clone_trait() => {
            Some(Instance {
                def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()),
                substs: rcvr_substs
            })
        }
        _ => {
            None
        }
    }
}

fn needs_fn_once_adapter_shim<'a, 'tcx>(actual_closure_kind: ty::ClosureKind,
                              trait_closure_kind: ty::ClosureKind)
    -> Result<bool, ()>
{
    match (actual_closure_kind, trait_closure_kind) {
        (ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
            (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
            (ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) => {
                // No adapter needed.
                Ok(false)
            }
        (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
            // The closure fn `llfn` is a `fn(&self, ...)`.  We want a
            // `fn(&mut self, ...)`. In fact, at trans time, these are
            // basically the same thing, so we can just return llfn.
            Ok(false)
        }
        (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
            (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
                // The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut
                // self, ...)`.  We want a `fn(self, ...)`. We can produce
                // this by doing something like:
                //
                //     fn call_once(self, ...) { call_mut(&self, ...) }
                //     fn call_once(mut self, ...) { call_mut(&mut self, ...) }
                //
                // These are both the same at trans time.
                Ok(true)
            }
        _ => Err(()),
    }
}

fn fn_once_adapter_instance<'a, 'tcx>(
                            tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            closure_did: DefId,
                            substs: ty::ClosureSubsts<'tcx>,
                            ) -> Instance<'tcx> {
    debug!("fn_once_adapter_shim({:?}, {:?})",
    closure_did,
    substs);
    let fn_once = tcx.lang_items().fn_once_trait().unwrap();
    let call_once = tcx.associated_items(fn_once)
        .find(|it| it.kind == ty::AssociatedKind::Method)
        .unwrap().def_id;
    let def = ty::InstanceDef::ClosureOnceShim { call_once };

    let self_ty = tcx.mk_closure_from_closure_substs(
        closure_did, substs);

    let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs);
    let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
    assert_eq!(sig.inputs().len(), 1);
    let substs = tcx.mk_substs([
                               Kind::from(self_ty),
                               Kind::from(sig.inputs()[0]),
    ].iter().cloned());

    debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
    Instance { def, substs }
}
<commit_msg>make match exaustive<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.

use hir::def_id::DefId;
use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
use ty::subst::{Kind, Subst};
use traits;
use syntax::abi::Abi;
use syntax::codemap::DUMMY_SP;
use util::ppaux;

use std::fmt;

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct Instance<'tcx> {
    pub def: InstanceDef<'tcx>,
    pub substs: &'tcx Substs<'tcx>,
}

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum InstanceDef<'tcx> {
    Item(DefId),
    Intrinsic(DefId),

    /// <fn() as FnTrait>::call_*
    /// def-id is FnTrait::call_*
    FnPtrShim(DefId, Ty<'tcx>),

    /// <Trait as Trait>::fn
    Virtual(DefId, usize),

    /// <[mut closure] as FnOnce>::call_once
    ClosureOnceShim { call_once: DefId },

    /// drop_in_place::<T>; None for empty drop glue.
    DropGlue(DefId, Option<Ty<'tcx>>),

    ///`<T as Clone>::clone` shim.
    CloneShim(DefId, Ty<'tcx>),
}

impl<'tcx> InstanceDef<'tcx> {
    #[inline]
    pub fn def_id(&self) -> DefId {
        match *self {
            InstanceDef::Item(def_id) |
            InstanceDef::FnPtrShim(def_id, _) |
            InstanceDef::Virtual(def_id, _) |
            InstanceDef::Intrinsic(def_id, ) |
            InstanceDef::ClosureOnceShim { call_once: def_id } |
            InstanceDef::DropGlue(def_id, _) |
            InstanceDef::CloneShim(def_id, _) => def_id
        }
    }

    #[inline]
    pub fn def_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
        tcx.type_of(self.def_id())
    }

    #[inline]
    pub fn attrs<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::Attributes<'tcx> {
        tcx.get_attrs(self.def_id())
    }
}

impl<'tcx> fmt::Display for Instance<'tcx> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        ppaux::parameterized(f, self.substs, self.def_id(), &[])?;
        match self.def {
            InstanceDef::Item(_) => Ok(()),
            InstanceDef::Intrinsic(_) => {
                write!(f, " - intrinsic")
            }
            InstanceDef::Virtual(_, num) => {
                write!(f, " - shim(#{})", num)
            }
            InstanceDef::FnPtrShim(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
            InstanceDef::ClosureOnceShim { .. } => {
                write!(f, " - shim")
            }
            InstanceDef::DropGlue(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
            InstanceDef::CloneShim(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
        }
    }
}

impl<'a, 'b, 'tcx> Instance<'tcx> {
    pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
               -> Instance<'tcx> {
        assert!(substs.is_normalized_for_trans() && !substs.has_escaping_regions(),
                "substs of instance {:?} not normalized for trans: {:?}",
                def_id, substs);
        Instance { def: InstanceDef::Item(def_id), substs: substs }
    }

    pub fn mono(tcx: TyCtxt<'a, 'tcx, 'b>, def_id: DefId) -> Instance<'tcx> {
        Instance::new(def_id, tcx.global_tcx().empty_substs_for_def_id(def_id))
    }

    #[inline]
    pub fn def_id(&self) -> DefId {
        self.def.def_id()
    }

    /// Resolve a (def_id, substs) pair to an (optional) instance -- most commonly,
    /// this is used to find the precise code that will run for a trait method invocation,
    /// if known.
    ///
    /// Returns `None` if we cannot resolve `Instance` to a specific instance.
    /// For example, in a context like this,
    ///
    /// ```
    /// fn foo<T: Debug>(t: T) { ... }
    /// ```
    ///
    /// trying to resolve `Debug::fmt` applied to `T` will yield `None`, because we do not
    /// know what code ought to run. (Note that this setting is also affected by the
    /// `RevealMode` in the parameter environment.)
    ///
    /// Presuming that coherence and type-check have succeeded, if this method is invoked
    /// in a monomorphic context (i.e., like during trans), then it is guaranteed to return
    /// `Some`.
    pub fn resolve(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                   param_env: ty::ParamEnv<'tcx>,
                   def_id: DefId,
                   substs: &'tcx Substs<'tcx>) -> Option<Instance<'tcx>> {
        debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
        let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) {
            debug!(" => associated item, attempting to find impl");
            let item = tcx.associated_item(def_id);
            resolve_associated_item(tcx, &item, param_env, trait_def_id, substs)
        } else {
            let ty = tcx.type_of(def_id);
            let item_type = tcx.trans_apply_param_substs(substs, &ty);

            let def = match item_type.sty {
                ty::TyFnDef(..) if {
                    let f = item_type.fn_sig(tcx);
                    f.abi() == Abi::RustIntrinsic ||
                        f.abi() == Abi::PlatformIntrinsic
                } =>
                {
                    debug!(" => intrinsic");
                    ty::InstanceDef::Intrinsic(def_id)
                }
                _ => {
                    if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
                        let ty = substs.type_at(0);
                        if ty.needs_drop(tcx, ty::ParamEnv::empty(traits::Reveal::All)) {
                            debug!(" => nontrivial drop glue");
                            ty::InstanceDef::DropGlue(def_id, Some(ty))
                        } else {
                            debug!(" => trivial drop glue");
                            ty::InstanceDef::DropGlue(def_id, None)
                        }
                    } else {
                        debug!(" => free item");
                        ty::InstanceDef::Item(def_id)
                    }
                }
            };
            Some(Instance {
                def: def,
                substs: substs
            })
        };
        debug!("resolve(def_id={:?}, substs={:?}) = {:?}", def_id, substs, result);
        result
    }
}

fn resolve_closure<'a, 'tcx>(
                   tcx: TyCtxt<'a, 'tcx, 'tcx>,
                   def_id: DefId,
                   substs: ty::ClosureSubsts<'tcx>,
                   requested_kind: ty::ClosureKind)
-> Instance<'tcx>
{
    let actual_kind = tcx.closure_kind(def_id);

    match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
        Ok(true) => fn_once_adapter_instance(tcx, def_id, substs),
        _ => Instance::new(def_id, substs.substs)
    }
}

fn resolve_associated_item<'a, 'tcx>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    trait_item: &ty::AssociatedItem,
    param_env: ty::ParamEnv<'tcx>,
    trait_id: DefId,
    rcvr_substs: &'tcx Substs<'tcx>
    ) -> Option<Instance<'tcx>> {
    let def_id = trait_item.def_id;
    debug!("resolve_associated_item(trait_item={:?}, \
                                    trait_id={:?}, \
           rcvr_substs={:?})",
           def_id, trait_id, rcvr_substs);

    let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
    let vtbl = tcx.trans_fulfill_obligation(DUMMY_SP, param_env, ty::Binder(trait_ref));

    // Now that we know which impl is being used, we can dispatch to
    // the actual function:
    match vtbl {
        traits::VtableImpl(impl_data) => {
            let (def_id, substs) = traits::find_associated_item(
                tcx, trait_item, rcvr_substs, &impl_data);
            let substs = tcx.erase_regions(&substs);
            Some(ty::Instance::new(def_id, substs))
        }
        traits::VtableGenerator(closure_data) => {
            Some(Instance {
                def: ty::InstanceDef::Item(closure_data.closure_def_id),
                substs: closure_data.substs.substs
            })
        }
        traits::VtableClosure(closure_data) => {
            let trait_closure_kind = tcx.lang_items().fn_trait_kind(trait_id).unwrap();
            Some(resolve_closure(tcx, closure_data.closure_def_id, closure_data.substs,
                                 trait_closure_kind))
        }
        traits::VtableFnPointer(ref data) => {
            Some(Instance {
                def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
                substs: rcvr_substs
            })
        }
        traits::VtableObject(ref data) => {
            let index = tcx.get_vtable_index_of_object_method(data, def_id);
            Some(Instance {
                def: ty::InstanceDef::Virtual(def_id, index),
                substs: rcvr_substs
            })
        }
        traits::VtableBuiltin(..) => {
            if let Some(_) = tcx.lang_items().clone_trait() {
                Some(Instance {
                    def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()),
                    substs: rcvr_substs
                })
            } else {
                None
            }
        }
        traits::VtableDefaultImpl(..) | traits::VtableParam(..) => None
    }
}

fn needs_fn_once_adapter_shim<'a, 'tcx>(actual_closure_kind: ty::ClosureKind,
                              trait_closure_kind: ty::ClosureKind)
    -> Result<bool, ()>
{
    match (actual_closure_kind, trait_closure_kind) {
        (ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
            (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
            (ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) => {
                // No adapter needed.
                Ok(false)
            }
        (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
            // The closure fn `llfn` is a `fn(&self, ...)`.  We want a
            // `fn(&mut self, ...)`. In fact, at trans time, these are
            // basically the same thing, so we can just return llfn.
            Ok(false)
        }
        (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
            (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
                // The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut
                // self, ...)`.  We want a `fn(self, ...)`. We can produce
                // this by doing something like:
                //
                //     fn call_once(self, ...) { call_mut(&self, ...) }
                //     fn call_once(mut self, ...) { call_mut(&mut self, ...) }
                //
                // These are both the same at trans time.
                Ok(true)
        }
        (ty::ClosureKind::FnMut, _) |
        (ty::ClosureKind::FnOnce, _) => Err(())
    }
}

fn fn_once_adapter_instance<'a, 'tcx>(
                            tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            closure_did: DefId,
                            substs: ty::ClosureSubsts<'tcx>,
                            ) -> Instance<'tcx> {
    debug!("fn_once_adapter_shim({:?}, {:?})",
    closure_did,
    substs);
    let fn_once = tcx.lang_items().fn_once_trait().unwrap();
    let call_once = tcx.associated_items(fn_once)
        .find(|it| it.kind == ty::AssociatedKind::Method)
        .unwrap().def_id;
    let def = ty::InstanceDef::ClosureOnceShim { call_once };

    let self_ty = tcx.mk_closure_from_closure_substs(
        closure_did, substs);

    let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs);
    let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
    assert_eq!(sig.inputs().len(), 1);
    let substs = tcx.mk_substs([
                               Kind::from(self_ty),
                               Kind::from(sig.inputs()[0]),
    ].iter().cloned());

    debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
    Instance { def, substs }
}
<|endoftext|>


<commit_before>use unicode_width::{UnicodeWidthStr,UnicodeWidthChar};
use super::Renderer;

/// State corresponding to a partially constructed line.
struct PartialLine {
    text: String,
    /// The width in character cells of the text, or
    /// current position.
    pos: usize,
}

impl PartialLine {
    pub fn new() -> PartialLine {
        PartialLine {
            text: String::new(),
            pos: 0,
        }
    }
}

/// A renderer which just outputs plain text.
pub struct TextRenderer {
    width: usize,
    lines: Vec<String>,
    /// True at the end of a block, meaning we should add
    /// a blank line if any other text is added.
    at_block_end: bool,
    partial_line: Option<PartialLine>,
}

impl TextRenderer {
    /// Construct a new empty TextRenderer.
    pub fn new(width: usize) -> TextRenderer {
        html_trace!("new({})", width);
        TextRenderer {
            width: width,
            lines: Vec::new(),
            at_block_end: false,
            partial_line: None,
        }
    }

    /// Take the partial line out of self, or create one
    /// if there wasn't one.
    fn take_partial_line(&mut self) -> PartialLine {
        if let Some(p) = self.partial_line.take() {
            p
        } else {
            PartialLine::new()
        }
    }

    pub fn add_subblock(&mut self, s: &str) {
        html_trace!("add_subblock({}, {})", self.width, s);
        self.lines.extend(s.lines().map(|l| l.into()));
    }

    fn push_line(&mut self, s: String) {
        self.lines.push(s);
    }
    fn flush_line(&mut self) {
        if let Some(s) = self.partial_line.take() {
            if s.text.len() > 0 {
                self.push_line(s.text);
            }
        }
    }

    pub fn into_string(mut self) -> String {
        self.flush_line();
        let mut result = String::new();
        for s in self.lines.into_iter() {
            result.push_str(&s);
            result.push('\n');
        }
        html_trace!("into_string({}, {:?})", self.width, result);
        result
    }

    fn into_lines(mut self) -> Vec<String> {
        self.flush_line();
        self.lines
    }
}

impl Renderer for TextRenderer {
    type Sub = TextRenderer;

    fn add_empty_line(&mut self) {
        html_trace!("add_empty_line()");
        self.flush_line();
        self.lines.push("".into());
        html_trace_quiet!("add_empty_line: at_block_end <- false");
        self.at_block_end = false;
        html_trace_quiet!("add_empty_line: new lines: {:?}", self.lines);
    }

    fn new_sub_renderer(&self, width: usize) -> Self::Sub {
        TextRenderer::new(width)
    }

    fn start_block(&mut self) {
        html_trace!("start_block({})", self.width);
        self.flush_line();
        if self.lines.len() > 0 {
            self.add_empty_line();
        }
        html_trace_quiet!("start_block; at_block_end <- false");
        self.at_block_end = false;
    }

    fn add_preformatted_block(&mut self, text: &str) {
        html_trace!("add_block({}, {})", self.width, text);
        self.start_block();
        self.add_subblock(text);
        html_trace_quiet!("add_block: at_block_end <- true");
        self.at_block_end = true;
    }

    fn end_block(&mut self) {
        self.at_block_end = true;
    }

    fn add_inline_text(&mut self, text: &str) {
        html_trace!("add_inline_text({}, {})", self.width, text);
        let mut partial = self.take_partial_line();
        for word in text.split_whitespace() {
            if self.width <= (partial.pos + 1) {
                self.push_line(partial.text);
                partial = self.take_partial_line();
            }
            let space_left = self.width - partial.pos - 1;
            let word_width = UnicodeWidthStr::width(word);
            if word_width <= space_left {
                /* It fits; no problem.  Add a space if not at the
                 * start of line.*/
                if partial.pos > 0 {
                    partial.text.push(' ');
                    partial.pos += 1;
                }
                partial.text.push_str(word);
                partial.pos += word_width;
                continue;
            }

            /* It doesn't fit.  If we're not at the start of the line,
             * then go to a new line. */
            if partial.pos > 0 {
                self.push_line(partial.text);
                partial = self.take_partial_line();
            }

            /* We're now at the start of a line. */
            if word_width > self.width {
                /* It doesn't fit at all on the line, so break it. */
                for c in word.chars() {
                    let c_width = UnicodeWidthChar::width(c).unwrap();
                    if c_width + partial.pos > self.width {
                        /* Break here */
                        self.push_line(partial.text);
                        partial = self.take_partial_line();
                    }
                    /* This might happen with really narrow spaces... */
                    assert!(c_width <= self.width);

                    partial.text.push(c);
                    partial.pos += c_width;
                }
            } else {
                partial.text.push_str(word);
                partial.pos += word_width;
            }
        }
        self.partial_line = Some(partial);
    }

    fn width(&self) -> usize {
        self.width
    }

    fn add_block_line(&mut self, line: &str)
    {
        self.add_subblock(line);
    }

    fn append_subrender<'a, I>(&mut self, other: Self::Sub,
                               prefixes: I)
                           where I:Iterator<Item=&'a str>
    {
        self.flush_line();
        self.lines.extend(other.into_lines()
                               .into_iter()
                               .zip(prefixes)
                               .map(|(line, prefix)| prefix.to_string() + &line));
    }

    fn append_columns<I>(&mut self, cols: I, separator: &str)
                           where I:IntoIterator<Item=Self::Sub> {
        unimplemented!()
        /*
        let cell_height = line_sets.iter()
                                   .map(|v| v.len())
                                   .max().unwrap_or(0);
        for i in 0..cell_height {
            let mut line = String::new();
            for (cellno, ls) in line_sets.iter().enumerate() {
                line.push_str(&format!("{: <width$}", ls.get(i).cloned().unwrap_or(""), width = used_widths[cellno]-1));
                if cellno != line_sets.len()-1 {
                    line.push('|')
                }
            }
            builder.add_block_line(&line);
        }
        */
    }

    fn empty(&self) -> bool {
        self.lines.len() == 0 && self.partial_line.is_none()
    }

    fn text_len(&self) -> usize {
        let mut result = 0;
        for line in &self.lines {
            result += UnicodeWidthStr::width(line.as_str());
        }
        if let Some(ref line) = self.partial_line {
            result += line.pos;
        }
        result
    }
}<commit_msg>Implement append_columns() (tests don't pass yet).<commit_after>use unicode_width::{UnicodeWidthStr,UnicodeWidthChar};
use super::Renderer;

/// State corresponding to a partially constructed line.
struct PartialLine {
    text: String,
    /// The width in character cells of the text, or
    /// current position.
    pos: usize,
}

impl PartialLine {
    pub fn new() -> PartialLine {
        PartialLine {
            text: String::new(),
            pos: 0,
        }
    }
}

/// A renderer which just outputs plain text.
pub struct TextRenderer {
    width: usize,
    lines: Vec<String>,
    /// True at the end of a block, meaning we should add
    /// a blank line if any other text is added.
    at_block_end: bool,
    partial_line: Option<PartialLine>,
}

impl TextRenderer {
    /// Construct a new empty TextRenderer.
    pub fn new(width: usize) -> TextRenderer {
        html_trace!("new({})", width);
        TextRenderer {
            width: width,
            lines: Vec::new(),
            at_block_end: false,
            partial_line: None,
        }
    }

    /// Take the partial line out of self, or create one
    /// if there wasn't one.
    fn take_partial_line(&mut self) -> PartialLine {
        if let Some(p) = self.partial_line.take() {
            p
        } else {
            PartialLine::new()
        }
    }

    pub fn add_subblock(&mut self, s: &str) {
        html_trace!("add_subblock({}, {})", self.width, s);
        self.lines.extend(s.lines().map(|l| l.into()));
    }

    fn push_line(&mut self, s: String) {
        self.lines.push(s);
    }
    fn flush_line(&mut self) {
        if let Some(s) = self.partial_line.take() {
            if s.text.len() > 0 {
                self.push_line(s.text);
            }
        }
    }

    pub fn into_string(mut self) -> String {
        self.flush_line();
        let mut result = String::new();
        for s in self.lines.into_iter() {
            result.push_str(&s);
            result.push('\n');
        }
        html_trace!("into_string({}, {:?})", self.width, result);
        result
    }

    fn into_lines(mut self) -> Vec<String> {
        self.flush_line();
        self.lines
    }
}

impl Renderer for TextRenderer {
    type Sub = TextRenderer;

    fn add_empty_line(&mut self) {
        html_trace!("add_empty_line()");
        self.flush_line();
        self.lines.push("".into());
        html_trace_quiet!("add_empty_line: at_block_end <- false");
        self.at_block_end = false;
        html_trace_quiet!("add_empty_line: new lines: {:?}", self.lines);
    }

    fn new_sub_renderer(&self, width: usize) -> Self::Sub {
        TextRenderer::new(width)
    }

    fn start_block(&mut self) {
        html_trace!("start_block({})", self.width);
        self.flush_line();
        if self.lines.len() > 0 {
            self.add_empty_line();
        }
        html_trace_quiet!("start_block; at_block_end <- false");
        self.at_block_end = false;
    }

    fn add_preformatted_block(&mut self, text: &str) {
        html_trace!("add_block({}, {})", self.width, text);
        self.start_block();
        self.add_subblock(text);
        html_trace_quiet!("add_block: at_block_end <- true");
        self.at_block_end = true;
    }

    fn end_block(&mut self) {
        self.at_block_end = true;
    }

    fn add_inline_text(&mut self, text: &str) {
        html_trace!("add_inline_text({}, {})", self.width, text);
        let mut partial = self.take_partial_line();
        for word in text.split_whitespace() {
            if self.width <= (partial.pos + 1) {
                self.push_line(partial.text);
                partial = self.take_partial_line();
            }
            let space_left = self.width - partial.pos - 1;
            let word_width = UnicodeWidthStr::width(word);
            if word_width <= space_left {
                /* It fits; no problem.  Add a space if not at the
                 * start of line.*/
                if partial.pos > 0 {
                    partial.text.push(' ');
                    partial.pos += 1;
                }
                partial.text.push_str(word);
                partial.pos += word_width;
                continue;
            }

            /* It doesn't fit.  If we're not at the start of the line,
             * then go to a new line. */
            if partial.pos > 0 {
                self.push_line(partial.text);
                partial = self.take_partial_line();
            }

            /* We're now at the start of a line. */
            if word_width > self.width {
                /* It doesn't fit at all on the line, so break it. */
                for c in word.chars() {
                    let c_width = UnicodeWidthChar::width(c).unwrap();
                    if c_width + partial.pos > self.width {
                        /* Break here */
                        self.push_line(partial.text);
                        partial = self.take_partial_line();
                    }
                    /* This might happen with really narrow spaces... */
                    assert!(c_width <= self.width);

                    partial.text.push(c);
                    partial.pos += c_width;
                }
            } else {
                partial.text.push_str(word);
                partial.pos += word_width;
            }
        }
        self.partial_line = Some(partial);
    }

    fn width(&self) -> usize {
        self.width
    }

    fn add_block_line(&mut self, line: &str)
    {
        self.add_subblock(line);
    }

    fn append_subrender<'a, I>(&mut self, other: Self::Sub,
                               prefixes: I)
                           where I:Iterator<Item=&'a str>
    {
        self.flush_line();
        self.lines.extend(other.into_lines()
                               .into_iter()
                               .zip(prefixes)
                               .map(|(line, prefix)| prefix.to_string() + &line));
    }

    fn append_columns<I>(&mut self, cols: I, separator: &str)
                           where I:IntoIterator<Item=Self::Sub> {
        self.flush_line();

        let line_sets = cols.into_iter()
                            .map(|sub_r| {
                                let width = sub_r.width;
                                (width, sub_r.into_lines()
                                             .into_iter()
                                             .map(|line| format!("{: <width$}", width=width))
                                             .collect())
                                 })
                            .collect::<Vec<(usize, Vec<String>)>>();

        let cell_height = line_sets.iter()
                                   .map(|&(_, ref v)| v.len())
                                   .max().unwrap_or(0);
        let spaces:String = (0..self.width).map(|_| ' ').collect();
        for i in 0..cell_height {
            let mut line = String::new();
            for (cellno, &(width, ref ls)) in line_sets.iter().enumerate() {
                let piece = ls.get(i).map(|s| s.as_str()).unwrap_or(&spaces[0..width]);
                line.push_str(piece);
                if cellno != line_sets.len()-1 {
                    line.push('|')
                }
            }
            self.add_block_line(&line);
        }
    }

    fn empty(&self) -> bool {
        self.lines.len() == 0 && self.partial_line.is_none()
    }

    fn text_len(&self) -> usize {
        let mut result = 0;
        for line in &self.lines {
            result += UnicodeWidthStr::width(line.as_str());
        }
        if let Some(ref line) = self.partial_line {
            result += line.pos;
        }
        result
    }
}<|endoftext|>


<commit_before>#![warn(clippy::all, clippy::pedantic)]

// TOO_MANY_LINES
fn good_lines() {
    /* println!("This is good."); */
    // println!("This is good.");
    /* */ // println!("This is good.");
    /* */ // println!("This is good.");
    /* */ // println!("This is good.");
    /* */ // println!("This is good.");
    /* println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good."); */
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
}

fn bad_lines() {
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
}

fn main() {}
<commit_msg>Updating to just warn for one test.<commit_after>#![warn(clippy::too_many_lines)]

fn good_lines() {
    /* println!("This is good."); */
    // println!("This is good.");
    /* */ // println!("This is good.");
    /* */ // println!("This is good.");
    /* */ // println!("This is good.");
    /* */ // println!("This is good.");
    /* println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good."); */
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
    println!("This is good.");
}

fn bad_lines() {
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
    println!("This is bad.");
}

fn main() {}
<|endoftext|>


<commit_before>#![allow(clippy::write_literal)]
#![warn(clippy::write_with_newline)]

use std::io::Write;

fn main() {
    let mut v = Vec::new();

    // These should fail
    write!(&mut v, "Hello\n");
    write!(&mut v, "Hello {}\n", "world");
    write!(&mut v, "Hello {} {}\n", "world", "#2");
    write!(&mut v, "{}\n", 1265);

    // These should be fine
    write!(&mut v, "");
    write!(&mut v, "Hello");
    writeln!(&mut v, "Hello");
    writeln!(&mut v, "Hello\n");
    writeln!(&mut v, "Hello {}\n", "world");
    write!(&mut v, "Issue\n{}", 1265);
    write!(&mut v, "{}", 1265);
    write!(&mut v, "\n{}", 1275);
    write!(&mut v, "\n\n");
    write!(&mut v, "like eof\n\n");
    write!(&mut v, "Hello {} {}\n\n", "world", "#2");
    writeln!(&mut v, "\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126
    writeln!(&mut v, "\nbla\n\n"); // #3126

    // Escaping
    write!(&mut v, "\\n"); // #3514
    write!(&mut v, "\\\n");
    write!(&mut v, "\\\\n");
}
<commit_msg>Add failing test for #3778 write_with_newline<commit_after>#![allow(clippy::write_literal)]
#![warn(clippy::write_with_newline)]

use std::io::Write;

fn main() {
    let mut v = Vec::new();

    // These should fail
    write!(&mut v, "Hello\n");
    write!(&mut v, "Hello {}\n", "world");
    write!(&mut v, "Hello {} {}\n", "world", "#2");
    write!(&mut v, "{}\n", 1265);

    // These should be fine
    write!(&mut v, "");
    write!(&mut v, "Hello");
    writeln!(&mut v, "Hello");
    writeln!(&mut v, "Hello\n");
    writeln!(&mut v, "Hello {}\n", "world");
    write!(&mut v, "Issue\n{}", 1265);
    write!(&mut v, "{}", 1265);
    write!(&mut v, "\n{}", 1275);
    write!(&mut v, "\n\n");
    write!(&mut v, "like eof\n\n");
    write!(&mut v, "Hello {} {}\n\n", "world", "#2");
    writeln!(&mut v, "\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126
    writeln!(&mut v, "\nbla\n\n"); // #3126

    // Escaping
    write!(&mut v, "\\n"); // #3514
    write!(&mut v, "\\\n");
    write!(&mut v, "\\\\n");

    // Raw strings
    write!(&mut v, r"\n"); // #3778
}
<|endoftext|>


<commit_before>//! Runfiles lookup library for Bazel-built Rust binaries and tests.
//!
//! USAGE:
//!
//! 1.  Depend on this runfiles library from your build rule:
//!     ```python
//!       rust_binary(
//!           name = "my_binary",
//!           ...
//!           data = ["//path/to/my/data.txt"],
//!           deps = ["@io_bazel_rules_rust//tools/runfiles"],
//!       )
//!     ```
//!
//! 2.  Import the runfiles library.
//!     ```
//!     extern crate runfiles;
//!
//!     use runfiles::Runfiles;
//!     ```
//!
//! 3.  Create a Runfiles object and use rlocation to look up runfile paths:
//!     ```ignore -- This doesn't work under rust_doc_test because argv[0] is not what we expect.
//!
//!     use runfiles::Runfiles;
//!
//!     let r = Runfiles::create().unwrap();
//!     let path = r.rlocation("my_workspace/path/to/my/data.txt");
//!
//!     let f = File::open(path).unwrap();
//!     // ...
//!     ```

use std::io;
use std::fs;
use std::path::PathBuf;
use std::path::Path;
use std::env;

pub struct Runfiles {
    runfiles_dir: PathBuf,
}

impl Runfiles {
    /// Creates a directory based Runfiles object.
    ///
    /// Manifest based creation is not currently supported.
    pub fn create() -> io::Result<Self> {
        Ok(Runfiles { runfiles_dir: find_runfiles_dir()? })
    }

    /// Returns the runtime path of a runfile.
    ///
    /// Runfiles are data-dependencies of Bazel-built binaries and tests.
    /// The returned path may not be valid. The caller should check the path's
    /// validity and that the path exists.
    pub fn rlocation(&self, path: impl AsRef<Path>) -> PathBuf {
        let path = path.as_ref();
        if path.is_absolute() {
            return path.to_path_buf();
        }
        self.runfiles_dir.join(path)
    }
}

/// Returns the .runfiles directory for the currently executing binary.
fn find_runfiles_dir() -> io::Result<PathBuf> {
    let exec_path = std::env::args().nth(0).expect("arg 0 was not set");

    let mut binary_path = PathBuf::from(&exec_path);
    loop {
        // Check for our neighboring $binary.runfiles directory.
        let mut runfiles_name = binary_path.file_name().unwrap().to_owned();
        runfiles_name.push(".runfiles");

        let runfiles_path = binary_path.with_file_name(&runfiles_name);
        if runfiles_path.is_dir() {
            return Ok(runfiles_path);
        }

        // Check if we're already under a *.runfiles directory.
        {
            // TODO: 1.28 adds Path::ancestors() which is a little simpler.
            let mut next = binary_path.parent();
            while let Some(ancestor) = next {
                if ancestor.file_name().map_or(false, |f| {
                    f.to_string_lossy().ends_with(".runfiles")
                })
                {
                    return Ok(ancestor.to_path_buf());
                }
                next = ancestor.parent();
            }
        }

        if !fs::symlink_metadata(&binary_path)?.file_type().is_symlink() {
            break;
        }
        // Follow symlinks and keep looking.
        binary_path = binary_path.read_link()?;
        if binary_path.is_relative() {
            binary_path = env::current_dir()?.join(binary_path)
        }
    }

    panic!("Failed to find .runfiles directory.");
}

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

    use std::io::prelude::*;
    use std::fs::File;

    #[test]
    fn test_can_read_data_from_runfiles() {
        let r = Runfiles::create().unwrap();

        let mut f = File::open(r.rlocation(
            "io_bazel_rules_rust/tools/runfiles/data/sample.txt",
        )).unwrap();

        let mut buffer = String::new();
        f.read_to_string(&mut buffer).unwrap();

        assert_eq!("Example Text!", buffer);
    }
}
<commit_msg>Fix symlink resolution in runfiles.rs (#214)<commit_after>//! Runfiles lookup library for Bazel-built Rust binaries and tests.
//!
//! USAGE:
//!
//! 1.  Depend on this runfiles library from your build rule:
//!     ```python
//!       rust_binary(
//!           name = "my_binary",
//!           ...
//!           data = ["//path/to/my/data.txt"],
//!           deps = ["@io_bazel_rules_rust//tools/runfiles"],
//!       )
//!     ```
//!
//! 2.  Import the runfiles library.
//!     ```
//!     extern crate runfiles;
//!
//!     use runfiles::Runfiles;
//!     ```
//!
//! 3.  Create a Runfiles object and use rlocation to look up runfile paths:
//!     ```ignore -- This doesn't work under rust_doc_test because argv[0] is not what we expect.
//!
//!     use runfiles::Runfiles;
//!
//!     let r = Runfiles::create().unwrap();
//!     let path = r.rlocation("my_workspace/path/to/my/data.txt");
//!
//!     let f = File::open(path).unwrap();
//!     // ...
//!     ```

use std::env;
use std::fs;
use std::io;
use std::path::Path;
use std::path::PathBuf;

pub struct Runfiles {
    runfiles_dir: PathBuf,
}

impl Runfiles {
    /// Creates a directory based Runfiles object.
    ///
    /// Manifest based creation is not currently supported.
    pub fn create() -> io::Result<Self> {
        Ok(Runfiles {
            runfiles_dir: find_runfiles_dir()?,
        })
    }

    /// Returns the runtime path of a runfile.
    ///
    /// Runfiles are data-dependencies of Bazel-built binaries and tests.
    /// The returned path may not be valid. The caller should check the path's
    /// validity and that the path exists.
    pub fn rlocation(&self, path: impl AsRef<Path>) -> PathBuf {
        let path = path.as_ref();
        if path.is_absolute() {
            return path.to_path_buf();
        }
        self.runfiles_dir.join(path)
    }
}

/// Returns the .runfiles directory for the currently executing binary.
fn find_runfiles_dir() -> io::Result<PathBuf> {
    let exec_path = std::env::args().nth(0).expect("arg 0 was not set");

    let mut binary_path = PathBuf::from(&exec_path);
    loop {
        // Check for our neighboring $binary.runfiles directory.
        let mut runfiles_name = binary_path.file_name().unwrap().to_owned();
        runfiles_name.push(".runfiles");

        let runfiles_path = binary_path.with_file_name(&runfiles_name);
        if runfiles_path.is_dir() {
            return Ok(runfiles_path);
        }

        // Check if we're already under a *.runfiles directory.
        {
            // TODO: 1.28 adds Path::ancestors() which is a little simpler.
            let mut next = binary_path.parent();
            while let Some(ancestor) = next {
                if ancestor
                    .file_name()
                    .map_or(false, |f| f.to_string_lossy().ends_with(".runfiles"))
                {
                    return Ok(ancestor.to_path_buf());
                }
                next = ancestor.parent();
            }
        }

        if !fs::symlink_metadata(&binary_path)?.file_type().is_symlink() {
            break;
        }
        // Follow symlinks and keep looking.
        let link_target = binary_path.read_link()?;
        binary_path = if link_target.is_absolute() {
            link_target
        } else {
            let link_dir = binary_path.parent().unwrap();
            env::current_dir()?.join(link_dir).join(link_target)
        }
    }

    Err(io::Error::new(
        io::ErrorKind::Other,
        "Failed to find .runfiles directory.",
    ))
}

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

    use std::fs::File;
    use std::io::prelude::*;

    #[test]
    fn test_can_read_data_from_runfiles() {
        let r = Runfiles::create().unwrap();

        let mut f =
            File::open(r.rlocation("io_bazel_rules_rust/tools/runfiles/data/sample.txt")).unwrap();

        let mut buffer = String::new();
        f.read_to_string(&mut buffer).unwrap();

        assert_eq!("Example Text!", buffer);
    }
}
<|endoftext|>


<commit_before>//! Implements a command for uploading dsym files.

use std::io;
use std::fs;
use std::env;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::mem;
use std::ffi::OsStr;

use clap::{App, Arg, ArgMatches};
use walkdir::{WalkDir, Iter as WalkDirIter};
use zip;

use prelude::*;
use api::{Api, DSymFile};
use utils::{TempFile, get_sha1_checksum};
use macho::is_macho_file;
use config::Config;

const BATCH_SIZE : usize = 15;

struct LocalFile {
    path: PathBuf,
    arc_name: String,
    checksum: String,
}

struct BatchIter {
    path: PathBuf,
    wd_iter: WalkDirIter,
    batch: Vec<LocalFile>,
}

impl BatchIter {
    pub fn new<P: AsRef<Path>>(path: P) -> BatchIter {
        BatchIter {
            path: path.as_ref().to_path_buf(),
            wd_iter: WalkDir::new(&path).into_iter(),
            batch: vec![],
        }
    }
}

impl Iterator for BatchIter {
    type Item = Result<Vec<LocalFile>>;

    fn next(&mut self) -> Option<Result<Vec<LocalFile>>> {
        loop {
            if let Some(dent_res) = self.wd_iter.next() {
                let dent = iter_try!(dent_res);
                let md = iter_try!(dent.metadata());
                if md.is_file() && is_macho_file(dent.path()) {
                    let name = Path::new("DebugSymbols")
                        .join(dent.path().strip_prefix(&self.path).unwrap());
                    println!("  {}", name.display());
                    self.batch.push(LocalFile {
                        path: dent.path().to_path_buf(),
                        arc_name: name.to_string_lossy().into_owned(),
                        checksum: iter_try!(get_sha1_checksum(dent.path())),
                    });
                    if self.batch.len() > BATCH_SIZE {
                        break;
                    }
                }
            } else {
                break;
            }
        }
        if self.batch.len() == 0 {
            None
        } else {
            Some(Ok(mem::replace(&mut self.batch, vec![])))
        }
    }
}

fn find_missing_files(api: &mut Api, files: Vec<LocalFile>, org: &str, project: &str)
    -> Result<Vec<LocalFile>>
{
    let missing = {
        let checksums : Vec<_> = files.iter().map(|ref x| x.checksum.as_str()).collect();
        api.find_missing_dsym_checksums(org, project, &checksums)?
    };
    let mut rv = vec![];
    for file in files.into_iter() {
        if missing.contains(&file.checksum) {
            rv.push(file)
        }
    }
    Ok(rv)
}

fn zip_up(files: &[LocalFile]) -> Result<TempFile> {
    println!("  Uploading a batch of missing files ...");
    let tf = TempFile::new()?;
    let mut zip = zip::ZipWriter::new(tf.open());
    for ref file in files {
        println!("    {}", file.arc_name);
        zip.start_file(file.arc_name.clone(),
            zip::CompressionMethod::Deflated)?;
        io::copy(&mut File::open(file.path.clone())?, &mut zip)?;
    }
    Ok(tf)
}

fn upload_dsyms(api: &mut Api, files: &[LocalFile],
                org: &str, project: &str) -> Result<Vec<DSymFile>> {
    let tf = zip_up(files)?;
    Ok(api.upload_dsyms(org, project, tf.path())?)
}

fn get_paths_from_env() -> Result<Vec<PathBuf>> {
    let mut rv = vec![];
    if let Some(base_path) = env::var_os("DWARF_DSYM_FOLDER_PATH") {
        for entry in fs::read_dir(base_path)? {
            let entry = entry?;
            if entry.path().extension() == Some(OsStr::new("dSYM")) &&
                fs::metadata(entry.path())?.is_dir() {
                rv.push(entry.path().to_path_buf());
            }
        }
    }
    Ok(rv)
}

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b>
{
    app
        .about("uploads debug symbols to a project")
        .arg(Arg::with_name("org")
             .value_name("ORG")
             .long("org")
             .short("o")
             .help("The organization slug"))
        .arg(Arg::with_name("project")
             .value_name("PROJECT")
             .long("project")
             .short("p")
             .help("The project slug"))
        .arg(Arg::with_name("paths")
             .value_name("PATH")
             .help("The path to the debug symbols")
             .multiple(true)
             .index(1))
}

pub fn execute<'a>(matches: &ArgMatches<'a>, config: &Config) -> Result<()> {
    let paths = match matches.values_of("paths") {
        Some(paths) => paths.map(|x| PathBuf::from(x)).collect(),
        None => get_paths_from_env()?,
    };
    let (org, project) = config.get_org_and_project(matches)?;
    let mut api = Api::new(config);

    println!("Uploading symbols");
    if paths.len() == 0 {
        println!("Warning: no paths were provided.");
    }

    for path in paths {
        println!("Finding symbols in {}...", path.display());
        for batch_res in BatchIter::new(path) {
            let missing = find_missing_files(&mut api, batch_res?, &org, &project)?;
            if missing.len() == 0 {
                continue;
            }
            println!("Detected missing files");
            let rv = upload_dsyms(&mut api, &missing, &org, &project)?;
            if rv.len() > 0 {
                println!("  Accepted debug symbols:");
                for df in rv {
                    println!("    {} ({}; {})", df.uuid, df.object_name, df.cpu_name);
                }
            }
        }
    }

    Ok(())
}
<commit_msg>Use WalkDir instead of read_dir to retrieve all dSYM folders<commit_after>//! Implements a command for uploading dsym files.

use std::io;
use std::fs;
use std::env;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::mem;
use std::ffi::OsStr;

use clap::{App, Arg, ArgMatches};
use walkdir::{WalkDir, Iter as WalkDirIter};
use zip;

use prelude::*;
use api::{Api, DSymFile};
use utils::{TempFile, get_sha1_checksum};
use macho::is_macho_file;
use config::Config;

const BATCH_SIZE : usize = 15;

struct LocalFile {
    path: PathBuf,
    arc_name: String,
    checksum: String,
}

struct BatchIter {
    path: PathBuf,
    wd_iter: WalkDirIter,
    batch: Vec<LocalFile>,
}

impl BatchIter {
    pub fn new<P: AsRef<Path>>(path: P) -> BatchIter {
        BatchIter {
            path: path.as_ref().to_path_buf(),
            wd_iter: WalkDir::new(&path).into_iter(),
            batch: vec![],
        }
    }
}

impl Iterator for BatchIter {
    type Item = Result<Vec<LocalFile>>;

    fn next(&mut self) -> Option<Result<Vec<LocalFile>>> {
        loop {
            if let Some(dent_res) = self.wd_iter.next() {
                let dent = iter_try!(dent_res);
                let md = iter_try!(dent.metadata());
                if md.is_file() && is_macho_file(dent.path()) {
                    let name = Path::new("DebugSymbols")
                        .join(dent.path().strip_prefix(&self.path).unwrap());
                    println!("  {}", name.display());
                    self.batch.push(LocalFile {
                        path: dent.path().to_path_buf(),
                        arc_name: name.to_string_lossy().into_owned(),
                        checksum: iter_try!(get_sha1_checksum(dent.path())),
                    });
                    if self.batch.len() > BATCH_SIZE {
                        break;
                    }
                }
            } else {
                break;
            }
        }
        if self.batch.len() == 0 {
            None
        } else {
            Some(Ok(mem::replace(&mut self.batch, vec![])))
        }
    }
}

fn find_missing_files(api: &mut Api, files: Vec<LocalFile>, org: &str, project: &str)
    -> Result<Vec<LocalFile>>
{
    let missing = {
        let checksums : Vec<_> = files.iter().map(|ref x| x.checksum.as_str()).collect();
        api.find_missing_dsym_checksums(org, project, &checksums)?
    };
    let mut rv = vec![];
    for file in files.into_iter() {
        if missing.contains(&file.checksum) {
            rv.push(file)
        }
    }
    Ok(rv)
}

fn zip_up(files: &[LocalFile]) -> Result<TempFile> {
    println!("  Uploading a batch of missing files ...");
    let tf = TempFile::new()?;
    let mut zip = zip::ZipWriter::new(tf.open());
    for ref file in files {
        println!("    {}", file.arc_name);
        zip.start_file(file.arc_name.clone(),
            zip::CompressionMethod::Deflated)?;
        io::copy(&mut File::open(file.path.clone())?, &mut zip)?;
    }
    Ok(tf)
}

fn upload_dsyms(api: &mut Api, files: &[LocalFile],
                org: &str, project: &str) -> Result<Vec<DSymFile>> {
    let tf = zip_up(files)?;
    Ok(api.upload_dsyms(org, project, tf.path())?)
}

fn get_paths_from_env() -> Result<Vec<PathBuf>> {
    let mut rv = vec![];
    if let Some(base_path) = env::var_os("DWARF_DSYM_FOLDER_PATH") {
        for entry in WalkDir::new(base_path) {
            let entry = entry?;
            if entry.path().extension() == Some(OsStr::new("dSYM")) &&
                fs::metadata(entry.path())?.is_dir() {
                rv.push(entry.path().to_path_buf());
            }
        }
    }
    Ok(rv)
}

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b>
{
    app
        .about("uploads debug symbols to a project")
        .arg(Arg::with_name("org")
             .value_name("ORG")
             .long("org")
             .short("o")
             .help("The organization slug"))
        .arg(Arg::with_name("project")
             .value_name("PROJECT")
             .long("project")
             .short("p")
             .help("The project slug"))
        .arg(Arg::with_name("paths")
             .value_name("PATH")
             .help("The path to the debug symbols")
             .multiple(true)
             .index(1))
}

pub fn execute<'a>(matches: &ArgMatches<'a>, config: &Config) -> Result<()> {
    let paths = match matches.values_of("paths") {
        Some(paths) => paths.map(|x| PathBuf::from(x)).collect(),
        None => get_paths_from_env()?,
    };
    let (org, project) = config.get_org_and_project(matches)?;
    let mut api = Api::new(config);

    println!("Uploading symbols");
    if paths.len() == 0 {
        println!("Warning: no paths were provided.");
    }

    for path in paths {
        println!("Finding symbols in {}...", path.display());
        for batch_res in BatchIter::new(path) {
            let missing = find_missing_files(&mut api, batch_res?, &org, &project)?;
            if missing.len() == 0 {
                continue;
            }
            println!("Detected missing files");
            let rv = upload_dsyms(&mut api, &missing, &org, &project)?;
            if rv.len() > 0 {
                println!("  Accepted debug symbols:");
                for df in rv {
                    println!("    {} ({}; {})", df.uuid, df.object_name, df.cpu_name);
                }
            }
        }
    }

    Ok(())
}
<|endoftext|>