<commit_before>//! Definition of the `JoinAll` combinator, waiting for all of a list of futures
//! to finish.

use std::prelude::v1::*;

use std::fmt;
use std::mem;

use {Future, IntoFuture, Poll, Async};

#[derive(Debug)]
enum ElemState<T> where T: Future {
    Pending(T),
    Done(T::Item),
}

/// A future which takes a list of futures and resolves with a vector of the
/// completed values.
///
/// This future is created with the `join_all` method.
#[must_use = "futures do nothing unless polled"]
pub struct JoinAll<I>
    where I: IntoIterator,
          I::Item: IntoFuture,
{
    elems: Vec<ElemState<<I::Item as IntoFuture>::Future>>,
}

impl<I> fmt::Debug for JoinAll<I>
    where I: IntoIterator,
          I::Item: IntoFuture,
          <<I as IntoIterator>::Item as IntoFuture>::Future: fmt::Debug,
          <<I as IntoIterator>::Item as IntoFuture>::Item: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("JoinAll")
            .field("elems", &self.elems)
            .finish()
    }
}

/// Creates a future which represents a collection of the results of the futures
/// given.
///
/// The returned future will drive execution for all of its underlying futures,
/// collecting the results into a destination `Vec<T>`. If any future returns
/// an error then all other futures will be canceled and an error will be
/// returned immediately. If all futures complete successfully, however, then
/// the returned future will succeed with a `Vec` of all the successful results.
///
/// # Examples
///
/// ```
/// use futures::future::*;
///
/// let f = join_all(vec![
///     ok::<u32, u32>(1),
///     ok::<u32, u32>(2),
///     ok::<u32, u32>(3),
/// ]);
/// let f = f.map(|x| {
///     assert_eq!(x, [1, 2, 3]);
/// });
///
/// let f = join_all(vec![
///     ok::<u32, u32>(1).boxed(),
///     err::<u32, u32>(2).boxed(),
///     ok::<u32, u32>(3).boxed(),
/// ]);
/// let f = f.then(|x| {
///     assert_eq!(x, Err(2));
///     x
/// });
/// ```
pub fn join_all<I>(i: I) -> JoinAll<I>
    where I: IntoIterator,
          I::Item: IntoFuture,
{
    let elems = i.into_iter().map(|f| {
        ElemState::Pending(f.into_future())
    }).collect();
    JoinAll { elems: elems }
}

impl<I> Future for JoinAll<I>
    where I: IntoIterator,
          I::Item: IntoFuture,
{
    type Item = Vec<<I::Item as IntoFuture>::Item>;
    type Error = <I::Item as IntoFuture>::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut all_done = true;

        for idx in 0 .. self.elems.len() {
            let done_val = match self.elems[idx] {
                ElemState::Pending(ref mut t) => {
                    match t.poll() {
                        Ok(Async::Ready(v)) => Ok(v),
                        Ok(Async::NotReady) => {
                            all_done = false;
                            continue
                        }
                        Err(e) => Err(e),
                    }
                }
                ElemState::Done(ref mut _v) => continue,
            };

            match done_val {
                Ok(v) => self.elems[idx] = ElemState::Done(v),
                Err(e) => {
                    // On completion drop all our associated resources
                    // ASAP.
                    self.elems = Vec::new();
                    return Err(e)
                }
            }
        }

        if all_done {
            let elems = mem::replace(&mut self.elems, Vec::new());
            let result = elems.into_iter().map(|e| {
                match e {
                    ElemState::Done(t) => t,
                    _ => unreachable!(),
                }
            }).collect();
            Ok(Async::Ready(result))
        } else {
            Ok(Async::NotReady)
        }
    }
}
<commit_msg>Noted ordering guarantee in join_all documentation<commit_after>//! Definition of the `JoinAll` combinator, waiting for all of a list of futures
//! to finish.

use std::prelude::v1::*;

use std::fmt;
use std::mem;

use {Future, IntoFuture, Poll, Async};

#[derive(Debug)]
enum ElemState<T> where T: Future {
    Pending(T),
    Done(T::Item),
}

/// A future which takes a list of futures and resolves with a vector of the
/// completed values.
///
/// This future is created with the `join_all` method.
#[must_use = "futures do nothing unless polled"]
pub struct JoinAll<I>
    where I: IntoIterator,
          I::Item: IntoFuture,
{
    elems: Vec<ElemState<<I::Item as IntoFuture>::Future>>,
}

impl<I> fmt::Debug for JoinAll<I>
    where I: IntoIterator,
          I::Item: IntoFuture,
          <<I as IntoIterator>::Item as IntoFuture>::Future: fmt::Debug,
          <<I as IntoIterator>::Item as IntoFuture>::Item: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("JoinAll")
            .field("elems", &self.elems)
            .finish()
    }
}

/// Creates a future which represents a collection of the results of the futures
/// given.
///
/// The returned future will drive execution for all of its underlying futures,
/// collecting the results into a destination `Vec<T>` in the same order as they
/// were provided. If any future returns an error then all other futures will be
/// canceled and an error will be returned immediately. If all futures complete
/// successfully, however, then the returned future will succeed with a `Vec` of
/// all the successful results.
///
/// # Examples
///
/// ```
/// use futures::future::*;
///
/// let f = join_all(vec![
///     ok::<u32, u32>(1),
///     ok::<u32, u32>(2),
///     ok::<u32, u32>(3),
/// ]);
/// let f = f.map(|x| {
///     assert_eq!(x, [1, 2, 3]);
/// });
///
/// let f = join_all(vec![
///     ok::<u32, u32>(1).boxed(),
///     err::<u32, u32>(2).boxed(),
///     ok::<u32, u32>(3).boxed(),
/// ]);
/// let f = f.then(|x| {
///     assert_eq!(x, Err(2));
///     x
/// });
/// ```
pub fn join_all<I>(i: I) -> JoinAll<I>
    where I: IntoIterator,
          I::Item: IntoFuture,
{
    let elems = i.into_iter().map(|f| {
        ElemState::Pending(f.into_future())
    }).collect();
    JoinAll { elems: elems }
}

impl<I> Future for JoinAll<I>
    where I: IntoIterator,
          I::Item: IntoFuture,
{
    type Item = Vec<<I::Item as IntoFuture>::Item>;
    type Error = <I::Item as IntoFuture>::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut all_done = true;

        for idx in 0 .. self.elems.len() {
            let done_val = match self.elems[idx] {
                ElemState::Pending(ref mut t) => {
                    match t.poll() {
                        Ok(Async::Ready(v)) => Ok(v),
                        Ok(Async::NotReady) => {
                            all_done = false;
                            continue
                        }
                        Err(e) => Err(e),
                    }
                }
                ElemState::Done(ref mut _v) => continue,
            };

            match done_val {
                Ok(v) => self.elems[idx] = ElemState::Done(v),
                Err(e) => {
                    // On completion drop all our associated resources
                    // ASAP.
                    self.elems = Vec::new();
                    return Err(e)
                }
            }
        }

        if all_done {
            let elems = mem::replace(&mut self.elems, Vec::new());
            let result = elems.into_iter().map(|e| {
                match e {
                    ElemState::Done(t) => t,
                    _ => unreachable!(),
                }
            }).collect();
            Ok(Async::Ready(result))
        } else {
            Ok(Async::NotReady)
        }
    }
}
<|endoftext|>


<commit_before>/*
 * This file is part of Twig (ported to Rust).
 *
 * For the copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a Token
 *
 * @author Colin Kiegel <kiegel@gmx.de>
 */

/////////////
// exports //
/////////////

pub mod stream;
pub use self::stream::Stream;

#[allow(dead_code)]
#[derive(Debug, PartialEq)]
pub enum Token {
    Eof,
    Text(String),
    BlockStart,
    VarStart,
    BlockEnd,
    VarEnd,
    Name(String),
    Number(String),
    String(String),
    Operator(String),
    Punctuation(String),
    InterpolationStart,
    InterpolationEnd,
}

#[allow(dead_code)]
#[derive(Debug, PartialEq)]
pub enum Type {
    Eof                = -1,
    Text               = 0,
    BlockStart         = 1,
    VarStart           = 2,
    BlockEnd           = 3,
    VarEnd             = 4,
    Name               = 5,
    Number             = 6,
    String             = 7,
    Operator           = 8,
    Punctuation        = 9,
    InterpolationStart = 10,
    InterpolationEnd   = 11,
}

#[allow(dead_code)]
#[allow(unused_variables)]
impl Token {
    pub fn get_value<'a>(&'a self) -> Option<&'a str> {
        match *self {
            Token::Eof => None,
            Token::Text(ref x) => Some(x),
            Token::BlockStart => None,
            Token::VarStart => None,
            Token::BlockEnd => None,
            Token::VarEnd => None,
            Token::Name(ref x) => Some(x),
            Token::Number(ref x) => Some(x),
            Token::String(ref x) => Some(x),
            Token::Operator(ref x) => Some(x),
            Token::Punctuation(ref x) => Some(x),
            Token::InterpolationStart => None,
            Token::InterpolationEnd => None,
        }
    }

    pub fn get_type(&self) -> Type {
        match *self {
            Token::Eof => Type::Eof,
            Token::Text(_) => Type::Text,
            Token::BlockStart => Type::BlockStart,
            Token::VarStart => Type::VarStart,
            Token::BlockEnd => Type::BlockEnd,
            Token::VarEnd => Type::VarEnd,
            Token::Name(_) => Type::Name,
            Token::Number(_) => Type::Number,
            Token::String(_) => Type::String,
            Token::Operator(_) => Type::Operator,
            Token::Punctuation(_) => Type::Punctuation,
            Token::InterpolationStart => Type::InterpolationStart,
            Token::InterpolationEnd => Type::InterpolationEnd,
        }
    }

    pub fn is_type(&self, typ: Type) -> bool {
        self.get_type() == typ
    }
}

impl ToString for Token {
    /// Returns a string representation of the token type.
    fn to_string(&self) -> String {
        let typ = self.get_type().get_name(false);
        match self.get_value() {
            Some(ref val) => format!("{typ}({val})", typ = typ, val = val),
            None          => format!("{typ}", typ = typ),
        }
    }
}

#[allow(dead_code)]
#[allow(unused_variables)]
impl Type {
    /// Returns the name of the token type (internal representation).
    ///
    /// # Arguments
    ///
    /// * `short` - short or long representation

    pub fn get_name(&self, short: bool) -> String {
         let name = match *self {
            Type::Eof => "EOF",
            Type::Text => "TEXT",
            Type::BlockStart => "BLOCK_START",
            Type::VarStart => "VAR_START",
            Type::BlockEnd => "BLOCK_END",
            Type::VarEnd => "VAR_END",
            Type::Name => "NAME",
            Type::Number => "NUMBER",
            Type::String => "STRING",
            Type::Operator => "OPERATOR",
            Type::Punctuation => "PUNCTUATION",
            Type::InterpolationStart => "INTERPOLATION_START",
            Type::InterpolationEnd => "INTERPOLATION_END",
        };

        if short {
            name.to_string()
        } else {
            format!("Token::Type::{}", name)
        }
    }

    /// Returns the description of the token type in plain english.

    pub fn get_description(&self) -> String {
         match *self {
            Type::Eof => "end of template",
            Type::Text => "text",
            Type::BlockStart => "begin of statement block",
            Type::VarStart => "begin of print statement",
            Type::BlockEnd => "end of statement block",
            Type::VarEnd => "end of print statement",
            Type::Name => "name",
            Type::Number => "number",
            Type::String => "string",
            Type::Operator => "operator",
            Type::Punctuation => "punctuation",
            Type::InterpolationStart => "begin of string interpolation",
            Type::InterpolationEnd => "end of string interpolation",
        }.to_string()
    }
}

impl ToString for Type {
    fn to_string(&self) -> String {
         self.get_name(true)
    }
}

#[cfg(test)]
mod test {
    use super::{Token, Type};

    #[test]
    fn new_token() {
        let token = Token::Text("Hello World!".to_string());
        assert_eq!(token.get_value().unwrap(), "Hello World!".to_string());
        assert!(token.is_type(Type::Text));
    }
}
<commit_msg>Token::Number split into Token::IntegerNumber vs. Token::FloatingNumber<commit_after>/*
 * This file is part of Twig (ported to Rust).
 *
 * For the copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a Token
 *
 * @author Colin Kiegel <kiegel@gmx.de>
 */

/////////////
// exports //
/////////////

pub mod stream;
pub use self::stream::Stream;

#[allow(dead_code)]
#[derive(Debug, PartialEq)]
pub enum Token {
    Eof,
    Text(String),
    BlockStart,
    VarStart,
    BlockEnd,
    VarEnd,
    Name(String),
    IntegerNumber(u64), // orig. Number
    FloatingNumber(f64), // orig. Number
    String(String),
    Operator(String),
    Punctuation(String),
    InterpolationStart,
    InterpolationEnd,
}

#[allow(dead_code)]
#[derive(Debug, PartialEq)]
pub enum Type {
    Eof                = -1,
    Text               = 0,
    BlockStart         = 1,
    VarStart           = 2,
    BlockEnd           = 3,
    VarEnd             = 4,
    Name               = 5,
    Number             = 6, // Floating or Integer
    String             = 7,
    Operator           = 8,
    Punctuation        = 9,
    InterpolationStart = 10,
    InterpolationEnd   = 11,
}

#[allow(dead_code)]
#[allow(unused_variables)]
impl Token {
    // Because of Number Types we need to return `String` copys instead of `&'a str`
    pub fn get_value<'a>(&'a self) -> Option<String> {
        match *self {
            Token::Eof => None,
            Token::Text(ref x) => Some(x.to_string()),
            Token::BlockStart => None,
            Token::VarStart => None,
            Token::BlockEnd => None,
            Token::VarEnd => None,
            Token::Name(ref x) => Some(x.to_string()),
            Token::IntegerNumber(ref x) => Some(x.to_string()),
            Token::FloatingNumber(ref x) => Some(x.to_string()),
            Token::String(ref x) => Some(x.to_string()),
            Token::Operator(ref x) => Some(x.to_string()),
            Token::Punctuation(ref x) => Some(x.to_string()),
            Token::InterpolationStart => None,
            Token::InterpolationEnd => None,
        }
    }

    pub fn get_type(&self) -> Type {
        match *self {
            Token::Eof => Type::Eof,
            Token::Text(_) => Type::Text,
            Token::BlockStart => Type::BlockStart,
            Token::VarStart => Type::VarStart,
            Token::BlockEnd => Type::BlockEnd,
            Token::VarEnd => Type::VarEnd,
            Token::Name(_) => Type::Name,
            Token::IntegerNumber(_) => Type::Number,
            Token::FloatingNumber(_) => Type::Number,
            Token::String(_) => Type::String,
            Token::Operator(_) => Type::Operator,
            Token::Punctuation(_) => Type::Punctuation,
            Token::InterpolationStart => Type::InterpolationStart,
            Token::InterpolationEnd => Type::InterpolationEnd,
        }
    }

    pub fn is_type(&self, typ: Type) -> bool {
        self.get_type() == typ
    }
}

impl ToString for Token {
    /// Returns a string representation of the token type.
    fn to_string(&self) -> String {
        let typ = self.get_type().get_name(false);
        match self.get_value() {
            Some(ref val) => format!("{typ}({val})", typ = typ, val = val),
            None          => format!("{typ}", typ = typ),
        }
    }
}

#[allow(dead_code)]
#[allow(unused_variables)]
impl Type {
    /// Returns the name of the token type (internal representation).
    ///
    /// # Arguments
    ///
    /// * `short` - short or long representation

    pub fn get_name(&self, short: bool) -> String {
         let name = match *self {
            Type::Eof => "EOF",
            Type::Text => "TEXT",
            Type::BlockStart => "BLOCK_START",
            Type::VarStart => "VAR_START",
            Type::BlockEnd => "BLOCK_END",
            Type::VarEnd => "VAR_END",
            Type::Name => "NAME",
            Type::Number => "NUMBER",
            Type::String => "STRING",
            Type::Operator => "OPERATOR",
            Type::Punctuation => "PUNCTUATION",
            Type::InterpolationStart => "INTERPOLATION_START",
            Type::InterpolationEnd => "INTERPOLATION_END",
        };

        if short {
            name.to_string()
        } else {
            format!("Token::Type::{}", name)
        }
    }

    /// Returns the description of the token type in plain english.

    pub fn get_description(&self) -> String {
         match *self {
            Type::Eof => "end of template",
            Type::Text => "text",
            Type::BlockStart => "begin of statement block",
            Type::VarStart => "begin of print statement",
            Type::BlockEnd => "end of statement block",
            Type::VarEnd => "end of print statement",
            Type::Name => "name",
            Type::Number => "number",
            Type::String => "string",
            Type::Operator => "operator",
            Type::Punctuation => "punctuation",
            Type::InterpolationStart => "begin of string interpolation",
            Type::InterpolationEnd => "end of string interpolation",
        }.to_string()
    }
}

impl ToString for Type {
    fn to_string(&self) -> String {
         self.get_name(true)
    }
}

#[cfg(test)]
mod test {
    use super::{Token, Type};

    #[test]
    fn new_token() {
        let token = Token::Text("Hello World!".to_string());
        assert_eq!(token.get_value().unwrap(), "Hello World!".to_string());
        assert!(token.is_type(Type::Text));
    }
}
<|endoftext|>


<commit_before>use namespace::Namespace;
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc::hir;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::traits::{self, IntercrateMode, FutureCompatOverlapErrorKind};
use rustc::ty::TyCtxt;
use rustc::ty::relate::TraitObjectMode;

use lint;

pub fn crate_inherent_impls_overlap_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                    crate_num: CrateNum) {
    assert_eq!(crate_num, LOCAL_CRATE);
    let krate = tcx.hir().krate();
    krate.visit_all_item_likes(&mut InherentOverlapChecker { tcx });
}

struct InherentOverlapChecker<'a, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'tcx, 'tcx>
}

impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
    fn check_for_common_items_in_impls(
        &self, impl1: DefId, impl2: DefId,
        overlap: traits::OverlapResult,
        used_to_be_allowed: Option<FutureCompatOverlapErrorKind>)
    {

        let name_and_namespace = |def_id| {
            let item = self.tcx.associated_item(def_id);
            (item.ident, Namespace::from(item.kind))
        };

        let impl_items1 = self.tcx.associated_item_def_ids(impl1);
        let impl_items2 = self.tcx.associated_item_def_ids(impl2);

        for &item1 in &impl_items1[..] {
            let (name, namespace) = name_and_namespace(item1);

            for &item2 in &impl_items2[..] {
                if (name, namespace) == name_and_namespace(item2) {
                    let node_id = self.tcx.hir().as_local_node_id(impl1);
                    let mut err = match used_to_be_allowed {
                        Some(kind) if node_id.is_some() => {
                            let lint = match kind {
                                FutureCompatOverlapErrorKind::Issue43355 =>
                                    lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
                                FutureCompatOverlapErrorKind::Issue33140 =>
                                    lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS,
                            };
                            self.tcx.struct_span_lint_node(
                                lint,
                                node_id.unwrap(),
                                self.tcx.span_of_impl(item1).unwrap(),
                                &format!("duplicate definitions with name `{}` (E0592)", name)
                            )
                        }
                        _ => {
                            struct_span_err!(self.tcx.sess,
                                             self.tcx.span_of_impl(item1).unwrap(),
                                             E0592,
                                             "duplicate definitions with name `{}`",
                                             name)
                        }
                    };

                    err.span_label(self.tcx.span_of_impl(item1).unwrap(),
                                   format!("duplicate definitions for `{}`", name));
                    err.span_label(self.tcx.span_of_impl(item2).unwrap(),
                                   format!("other definition for `{}`", name));

                    for cause in &overlap.intercrate_ambiguity_causes {
                        cause.add_intercrate_ambiguity_hint(&mut err);
                    }

                    if overlap.involves_placeholder {
                        traits::add_placeholder_note(&mut err);
                    }

                    err.emit();
                }
            }
        }
    }

    fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) {
        let impls = self.tcx.inherent_impls(ty_def_id);

        for (i, &impl1_def_id) in impls.iter().enumerate() {
            for &impl2_def_id in &impls[(i + 1)..] {
                // First, check if the impl was forbidden under the
                // old rules. In that case, just have an error.
                let used_to_be_allowed = traits::overlapping_impls(
                    self.tcx,
                    impl1_def_id,
                    impl2_def_id,
                    IntercrateMode::Issue43355,
                    TraitObjectMode::NoSquash,
                    |overlap| {
                        self.check_for_common_items_in_impls(
                            impl1_def_id,
                            impl2_def_id,
                            overlap,
                            None,
                        );
                        false
                    },
                    || true,
                );

                if !used_to_be_allowed {
                    continue;
                }

                // Then, check if the impl was forbidden under only
                // #43355. In that case, emit an #43355 error.
                let used_to_be_allowed = traits::overlapping_impls(
                    self.tcx,
                    impl1_def_id,
                    impl2_def_id,
                    IntercrateMode::Fixed,
                    TraitObjectMode::NoSquash,
                    |overlap| {
                        self.check_for_common_items_in_impls(
                            impl1_def_id,
                            impl2_def_id,
                            overlap,
                            Some(FutureCompatOverlapErrorKind::Issue43355),
                        );
                        false
                    },
                    || true,
                );

                if !used_to_be_allowed {
                    continue;
                }

                // Then, check if the impl was forbidden under
                // #33140. In that case, emit a #33140 error.
                traits::overlapping_impls(
                    self.tcx,
                    impl1_def_id,
                    impl2_def_id,
                    IntercrateMode::Fixed,
                    TraitObjectMode::SquashAutoTraitsIssue33140,
                    |overlap| {
                        self.check_for_common_items_in_impls(
                            impl1_def_id,
                            impl2_def_id,
                            overlap,
                            Some(FutureCompatOverlapErrorKind::Issue33140),
                        );
                        false
                    },
                    || true,
                );
            }
        }
    }
}

impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentOverlapChecker<'a, 'tcx> {
    fn visit_item(&mut self, item: &'v hir::Item) {
        match item.node {
            hir::ItemKind::Enum(..) |
            hir::ItemKind::Struct(..) |
            hir::ItemKind::Trait(..) |
            hir::ItemKind::Union(..) => {
                let type_def_id = self.tcx.hir().local_def_id(item.id);
                self.check_for_overlapping_inherent_impls(type_def_id);
            }
            _ => {}
        }
    }

    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
    }

    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
    }
}
<commit_msg>Revert "fix stupid bug"<commit_after>use namespace::Namespace;
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc::hir;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::traits::{self, IntercrateMode, FutureCompatOverlapErrorKind};
use rustc::ty::TyCtxt;
use rustc::ty::relate::TraitObjectMode;

use lint;

pub fn crate_inherent_impls_overlap_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                    crate_num: CrateNum) {
    assert_eq!(crate_num, LOCAL_CRATE);
    let krate = tcx.hir().krate();
    krate.visit_all_item_likes(&mut InherentOverlapChecker { tcx });
}

struct InherentOverlapChecker<'a, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'tcx, 'tcx>
}

impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
    fn check_for_common_items_in_impls(
        &self, impl1: DefId, impl2: DefId,
        overlap: traits::OverlapResult,
        used_to_be_allowed: Option<FutureCompatOverlapErrorKind>)
    {

        let name_and_namespace = |def_id| {
            let item = self.tcx.associated_item(def_id);
            (item.ident, Namespace::from(item.kind))
        };

        let impl_items1 = self.tcx.associated_item_def_ids(impl1);
        let impl_items2 = self.tcx.associated_item_def_ids(impl2);

        for &item1 in &impl_items1[..] {
            let (name, namespace) = name_and_namespace(item1);

            for &item2 in &impl_items2[..] {
                if (name, namespace) == name_and_namespace(item2) {
                    let node_id = self.tcx.hir().as_local_node_id(impl1);
                    let mut err = match used_to_be_allowed {
                        Some(kind) if node_id.is_some() => {
                            let lint = match kind {
                                FutureCompatOverlapErrorKind::Issue43355 =>
                                    lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
                                FutureCompatOverlapErrorKind::Issue33140 =>
                                    lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS,
                            };
                            self.tcx.struct_span_lint_node(
                                lint,
                                node_id.unwrap(),
                                self.tcx.span_of_impl(item1).unwrap(),
                                &format!("duplicate definitions with name `{}` (E0592)", name)
                            )
                        }
                        _ => {
                            struct_span_err!(self.tcx.sess,
                                             self.tcx.span_of_impl(item1).unwrap(),
                                             E0592,
                                             "duplicate definitions with name `{}`",
                                             name)
                        }
                    };

                    err.span_label(self.tcx.span_of_impl(item1).unwrap(),
                                   format!("duplicate definitions for `{}`", name));
                    err.span_label(self.tcx.span_of_impl(item2).unwrap(),
                                   format!("other definition for `{}`", name));

                    for cause in &overlap.intercrate_ambiguity_causes {
                        cause.add_intercrate_ambiguity_hint(&mut err);
                    }

                    if overlap.involves_placeholder {
                        traits::add_placeholder_note(&mut err);
                    }

                    err.emit();
                }
            }
        }
    }

    fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) {
        let impls = self.tcx.inherent_impls(ty_def_id);

        for (i, &impl1_def_id) in impls.iter().enumerate() {
            for &impl2_def_id in &impls[(i + 1)..] {
                let mut used_to_be_allowed = traits::overlapping_impls(
                    self.tcx,
                    impl1_def_id,
                    impl2_def_id,
                    IntercrateMode::Issue43355,
                    TraitObjectMode::NoSquash,
                    |overlap| {
                        self.check_for_common_items_in_impls(
                            impl1_def_id,
                            impl2_def_id,
                            overlap,
                            Some(FutureCompatOverlapErrorKind::Issue43355),
                        );
                        false
                    },
                    || true,
                );

                if used_to_be_allowed {
                    used_to_be_allowed = traits::overlapping_impls(
                        self.tcx,
                        impl1_def_id,
                        impl2_def_id,
                        IntercrateMode::Fixed,
                        TraitObjectMode::NoSquash,
                        |overlap| {
                            self.check_for_common_items_in_impls(
                                impl1_def_id,
                                impl2_def_id,
                                overlap,
                                None,
                            );
                            false
                        },
                        || true,
                    );
                }

                if used_to_be_allowed {
                    traits::overlapping_impls(
                        self.tcx,
                        impl1_def_id,
                        impl2_def_id,
                        IntercrateMode::Fixed,
                        TraitObjectMode::SquashAutoTraitsIssue33140,
                        |overlap| {
                            self.check_for_common_items_in_impls(
                                impl1_def_id,
                                impl2_def_id,
                                overlap,
                                Some(FutureCompatOverlapErrorKind::Issue33140),
                            );
                            false
                        },
                        || true,
                    );
                }
            }
        }
    }
}

impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentOverlapChecker<'a, 'tcx> {
    fn visit_item(&mut self, item: &'v hir::Item) {
        match item.node {
            hir::ItemKind::Enum(..) |
            hir::ItemKind::Struct(..) |
            hir::ItemKind::Trait(..) |
            hir::ItemKind::Union(..) => {
                let type_def_id = self.tcx.hir().local_def_id(item.id);
                self.check_for_overlapping_inherent_impls(type_def_id);
            }
            _ => {}
        }
    }

    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
    }

    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
    }
}
<|endoftext|>


<commit_before>extern crate rtlsdr;

use std::os::raw::{c_void, c_uchar};
use std::ptr;
use rtlsdr::Error;
use std::time::Duration;
use std::thread;

#[allow(unused_mut)]
fn sdr_config(dev: &rtlsdr::Device) -> Error {
    let (m, p, s, mut err) = dev.get_usb_strings();
    match err {
        Error::NoError => println!("set_xtal_freq successful"),
        _ => return err,
    };
    println!("m: {}\n p: {}\n s: {}\n err: {:?}\n", m, p, s, err);

    // ---------- Get/Set/Get Hardware Info ----------
    println!("1. Getting hardware info...");
    let (mut hw_info, mut err) = dev.get_hw_info();

    println!("Error: {:?}", err);
    println!("Vendor ID:             {:?}", hw_info.vendor_id);
    println!("Product ID:            {:?}", hw_info.product_id);
    println!("Manufacturer:          {:?}", hw_info.manufact);
    println!("Product:               {:?}", hw_info.product);
    println!("Serial number:         {:?}", hw_info.serial);
    println!("Serial number enabled: {:?}", hw_info.have_serial);
    println!("IR endpoint enabled:   {:?}", hw_info.enable_ir);
    println!("Remote wakeup enabled: {:?}", hw_info.remote_wakeup);
    println!("");

    println!("Writing hardware info...");
    err = dev.set_hw_info(&hw_info);
    println!("Writing hardware info return message: {:?}\n", err);

    println!("2. Getting hardware info...");
    let (hw_info, mut err) = dev.get_hw_info();

    println!("Error: {:?}", err);
    println!("Vendor ID:             {:?}", hw_info.vendor_id);
    println!("Product ID:            {:?}", hw_info.product_id);
    println!("Manufacturer:          {:?}", hw_info.manufact);
    println!("Product:               {:?}", hw_info.product);
    println!("Serial number:         {:?}", hw_info.serial);
    println!("Serial number enabled: {:?}", hw_info.have_serial);
    println!("IR endpoint enabled:   {:?}", hw_info.enable_ir);
    println!("Remote wakeup enabled: {:?}", hw_info.remote_wakeup);
    println!("");

    // ---------- Get Tuner Gain ----------
    println!("get_tuner_type: {}", dev.get_tuner_type());
    err = dev.set_xtal_freq(28800000, 28800000);
    match err {
        Error::NoError => println!("set_xtal_freq - 28800000"),
        _ => return err,
    };
    println!("");

    // ---------- Set Tuner Gain ----------
    err = dev.set_tuner_gain_mode(true);
    match err {
        Error::NoError => println!("set_tuner_gain_mode successful..."),
        _ => return err,
    };

    let (gains, mut err) = dev.get_tuner_gains();
    match err {
        Error::NoError => println!("get_tuner_gains successful..."),
        _ => println!("get_tuner_gains failed - {:?}", err), // return err,
    };

    println!("\ntuner gains:  {:?}\n", gains);

    err = dev.set_tuner_gain(gains[2]);
    match err {
        Error::NoError => println!("set_tuner_gain {:?} successful...", gains[2]),
        _ => return err,
    };
    println!("");

    // ---------- Get/Set Sample Rate ----------
    let samplerate: i32 = 2083334;
    err = dev.set_sample_rate(samplerate);
    match err {
        Error::NoError => println!("set_sample_rate {} successful...", samplerate),
        _ => return err,
    };

    println!("get_sample_rate {} successful...\n", dev.get_sample_rate());

    // ---------- Get/Set Xtal Freq ----------
    let (mut rtl_freq, mut tuner_freq, mut err) = dev.get_xtal_freq();
    match err {
        Error::NoError => {
            println!("get_xtal_freq successful - rtl_freq: {}, tuner_freq: {}",
                     rtl_freq,
                     tuner_freq)
        }
        _ => return err,
    };

    rtl_freq = 28800000;
    tuner_freq = 28800000;

    err = dev.set_xtal_freq(rtl_freq, tuner_freq);
    match err {
        Error::NoError => {
            println!("set_xtal_freq successful - rtl_freq: {}, tuner_freq: {}",
                     rtl_freq,
                     tuner_freq)
        }
        _ => return err,
    };
    println!("");

    // ---------- Get/Set Center Freq ----------
    err = dev.set_center_freq(978000000);
    match err {
        Error::NoError => println!("set_center_freq successful - 978000000"),
        _ => return err,
    };

    println!("get_center_freq: {}\n", dev.get_center_freq());

    // ---------- Set Tuner Bandwidth ----------
    let bw: i32 = 1000000;
    println!("Setting bandwidth: {}", bw);

    err = dev.set_tuner_bandwidth(bw);
    match err {
        Error::NoError => println!("set_tuner_bandwidth {} Successful", bw),
        _ => return err,
    };
    println!("");

    // ---------- Buffer Reset ----------
    err = dev.reset_buffer();
    match err {
        Error::NoError => println!("reset_buffer successful..."),
        _ => return err,
    };

    // ---------- Get/Set Freq Correction ----------
    let mut freq_corr = dev.get_freq_correction();
    println!("get_freq_correction - {}", freq_corr);

    freq_corr += 1;
    let err = dev.set_freq_correction(freq_corr);
    match err {
        Error::NoError => println!("set_freq_correction successful - {}", freq_corr),
        _ => return err,
    };
    println!("");
    // ----------  ----------
    Error::NoError
}

unsafe extern "C" fn read_async_callback(buf: *mut c_uchar, len: u32, ctx: *mut c_void) {
    let _ = ctx;
    let v = Vec::<u8>::from_raw_parts(buf, len as usize, len as usize);
    println!("----- read_async_callback buffer size - {}", len);
    println!("----- {} {} {} {} {} {}",
             v[0],
             v[1],
             v[2],
             v[3],
             v[4],
             v[5]);
}

fn main() {
    // ---------- Device Check ----------
    let count = rtlsdr::get_device_count();
    if count == 0 {
        println!("No devices found, exiting.");
        return;
    }

    for i in 0..count {
        let (m, p, s, err) = rtlsdr::get_device_usb_strings(i);
        println!("get_device_usb_strings: {:?} - {} {} {}", err, m, p, s);
    }

    let index = 0;
    println!("===== Device name, index {}: {} =====",
             index,
             rtlsdr::get_device_name(0));
    println!("===== Running tests using device indx: 0 =====\n");

    let (dev, mut err) = rtlsdr::open(index);
    match err {
        Error::NoError => println!("open successful"),
        _ => return,
    }

    err = sdr_config(&dev);
    match err {
        Error::NoError => println!("sdr_config successful..."),
        _ => return,
    }

    println!("calling read_sync...");
    for i in 0..10 {
        let (_, read_count, err) = dev.read_sync(rtlsdr::DEFAULT_BUF_LENGTH);
        println!("----- read_sync requested iteration {} -----", i);
        println!("\tread_sync requested - {}", rtlsdr::DEFAULT_BUF_LENGTH);
        println!("\tread_sync received  - {}", read_count);
        println!("\tread_sync err msg   - {:?}", err);
    }

    dev.reset_buffer();

    // read_async is a blocking call and doesn't return until
    // async_stop is explicitly called, so we spawn a thread
    // that sleeps for a bit while our async callback runs...
    let d = dev.clone();
    thread::spawn(move || {
        println!("async_stop thread sleeping for 5 seconds...");
        thread::sleep(Duration::from_millis(5000));
        println!("async_stop thread awake, canceling read async...");
        d.cancel_async();
    });

    println!("calling read_async...");
    err = dev.read_async(Some(read_async_callback),
                         ptr::null_mut(),
                         rtlsdr::DEFAULT_ASYNC_BUF_NUMBER,
                         rtlsdr::DEFAULT_BUF_LENGTH);
    match err {
        Error::NoError => println!("device close successful..."),
        _ => println!("dev close error - {:?}", err),
    }

    err = dev.close();
    match err {
        Error::NoError => println!("device close successful..."),
        _ => println!("dev close error - {:?}", err),
    }
}
<commit_msg>update comment<commit_after>extern crate rtlsdr;

use std::os::raw::{c_void, c_uchar};
use std::ptr;
use rtlsdr::Error;
use std::time::Duration;
use std::thread;

#[allow(unused_mut)]
fn sdr_config(dev: &rtlsdr::Device) -> Error {
    let (m, p, s, mut err) = dev.get_usb_strings();
    match err {
        Error::NoError => println!("set_xtal_freq successful"),
        _ => return err,
    };
    println!("m: {}\n p: {}\n s: {}\n err: {:?}\n", m, p, s, err);

    // ---------- Get/Set/Get Hardware Info ----------
    println!("1. Getting hardware info...");
    let (mut hw_info, mut err) = dev.get_hw_info();

    println!("Error: {:?}", err);
    println!("Vendor ID:             {:?}", hw_info.vendor_id);
    println!("Product ID:            {:?}", hw_info.product_id);
    println!("Manufacturer:          {:?}", hw_info.manufact);
    println!("Product:               {:?}", hw_info.product);
    println!("Serial number:         {:?}", hw_info.serial);
    println!("Serial number enabled: {:?}", hw_info.have_serial);
    println!("IR endpoint enabled:   {:?}", hw_info.enable_ir);
    println!("Remote wakeup enabled: {:?}", hw_info.remote_wakeup);
    println!("");

    println!("Writing hardware info...");
    err = dev.set_hw_info(&hw_info);
    println!("Writing hardware info return message: {:?}\n", err);

    println!("2. Getting hardware info...");
    let (hw_info, mut err) = dev.get_hw_info();

    println!("Error: {:?}", err);
    println!("Vendor ID:             {:?}", hw_info.vendor_id);
    println!("Product ID:            {:?}", hw_info.product_id);
    println!("Manufacturer:          {:?}", hw_info.manufact);
    println!("Product:               {:?}", hw_info.product);
    println!("Serial number:         {:?}", hw_info.serial);
    println!("Serial number enabled: {:?}", hw_info.have_serial);
    println!("IR endpoint enabled:   {:?}", hw_info.enable_ir);
    println!("Remote wakeup enabled: {:?}", hw_info.remote_wakeup);
    println!("");

    // ---------- Get Tuner Gain ----------
    println!("get_tuner_type: {}", dev.get_tuner_type());
    err = dev.set_xtal_freq(28800000, 28800000);
    match err {
        Error::NoError => println!("set_xtal_freq - 28800000"),
        _ => return err,
    };
    println!("");

    // ---------- Set Tuner Gain ----------
    err = dev.set_tuner_gain_mode(true);
    match err {
        Error::NoError => println!("set_tuner_gain_mode successful..."),
        _ => return err,
    };

    let (gains, mut err) = dev.get_tuner_gains();
    match err {
        Error::NoError => println!("get_tuner_gains successful..."),
        _ => println!("get_tuner_gains failed - {:?}", err), // return err,
    };

    println!("\ntuner gains:  {:?}\n", gains);

    err = dev.set_tuner_gain(gains[2]);
    match err {
        Error::NoError => println!("set_tuner_gain {:?} successful...", gains[2]),
        _ => return err,
    };
    println!("");

    // ---------- Get/Set Sample Rate ----------
    let samplerate: i32 = 2083334;
    err = dev.set_sample_rate(samplerate);
    match err {
        Error::NoError => println!("set_sample_rate {} successful...", samplerate),
        _ => return err,
    };

    println!("get_sample_rate {} successful...\n", dev.get_sample_rate());

    // ---------- Get/Set Xtal Freq ----------
    let (mut rtl_freq, mut tuner_freq, mut err) = dev.get_xtal_freq();
    match err {
        Error::NoError => {
            println!("get_xtal_freq successful - rtl_freq: {}, tuner_freq: {}",
                     rtl_freq,
                     tuner_freq)
        }
        _ => return err,
    };

    rtl_freq = 28800000;
    tuner_freq = 28800000;

    err = dev.set_xtal_freq(rtl_freq, tuner_freq);
    match err {
        Error::NoError => {
            println!("set_xtal_freq successful - rtl_freq: {}, tuner_freq: {}",
                     rtl_freq,
                     tuner_freq)
        }
        _ => return err,
    };
    println!("");

    // ---------- Get/Set Center Freq ----------
    err = dev.set_center_freq(978000000);
    match err {
        Error::NoError => println!("set_center_freq successful - 978000000"),
        _ => return err,
    };

    println!("get_center_freq: {}\n", dev.get_center_freq());

    // ---------- Set Tuner Bandwidth ----------
    let bw: i32 = 1000000;
    println!("Setting bandwidth: {}", bw);

    err = dev.set_tuner_bandwidth(bw);
    match err {
        Error::NoError => println!("set_tuner_bandwidth {} Successful", bw),
        _ => return err,
    };
    println!("");

    // ---------- Buffer Reset ----------
    err = dev.reset_buffer();
    match err {
        Error::NoError => println!("reset_buffer successful..."),
        _ => return err,
    };

    // ---------- Get/Set Freq Correction ----------
    let mut freq_corr = dev.get_freq_correction();
    println!("get_freq_correction - {}", freq_corr);

    freq_corr += 1;
    let err = dev.set_freq_correction(freq_corr);
    match err {
        Error::NoError => println!("set_freq_correction successful - {}", freq_corr),
        _ => return err,
    };
    println!("");
    // ----------  ----------
    Error::NoError
}

unsafe extern "C" fn read_async_callback(buf: *mut c_uchar, len: u32, ctx: *mut c_void) {
    let _ = ctx;
    let v = Vec::<u8>::from_raw_parts(buf, len as usize, len as usize);
    println!("----- read_async_callback buffer size - {}", len);
    println!("----- {} {} {} {} {} {}",
             v[0],
             v[1],
             v[2],
             v[3],
             v[4],
             v[5]);
}

fn main() {
    // ---------- Device Check ----------
    let count = rtlsdr::get_device_count();
    if count == 0 {
        println!("No devices found, exiting.");
        return;
    }

    for i in 0..count {
        let (m, p, s, err) = rtlsdr::get_device_usb_strings(i);
        println!("get_device_usb_strings: {:?} - {} {} {}", err, m, p, s);
    }

    let index = 0;
    println!("===== Device name, index {}: {} =====",
             index,
             rtlsdr::get_device_name(0));
    println!("===== Running tests using device indx: 0 =====\n");

    let (dev, mut err) = rtlsdr::open(index);
    match err {
        Error::NoError => println!("open successful"),
        _ => return,
    }

    err = sdr_config(&dev);
    match err {
        Error::NoError => println!("sdr_config successful..."),
        _ => return,
    }

    println!("calling read_sync...");
    for i in 0..10 {
        let (_, read_count, err) = dev.read_sync(rtlsdr::DEFAULT_BUF_LENGTH);
        println!("----- read_sync requested iteration {} -----", i);
        println!("\tread_sync requested - {}", rtlsdr::DEFAULT_BUF_LENGTH);
        println!("\tread_sync received  - {}", read_count);
        println!("\tread_sync err msg   - {:?}", err);
    }

    dev.reset_buffer();

    // read_async is a blocking call and doesn't return until
    // async_stop is explicitly called, so we spawn a thread
    // that sleeps for a bit while our async callback runs...
    let d = dev.clone();
    thread::spawn(move || {
        println!("async_stop thread sleeping for 5 seconds...");
        thread::sleep(Duration::from_millis(5000));
        println!("async_stop thread awake, canceling read async...");
        d.cancel_async();
    });

    println!("calling read_async...");
    err = dev.read_async(Some(read_async_callback),
                         ptr::null_mut(),
                         rtlsdr::DEFAULT_ASYNC_BUF_NUMBER,
                         rtlsdr::DEFAULT_BUF_LENGTH);
    match err {
        Error::NoError => println!("read_async returned successfully..."),
        _ => println!("read_async return error - {:?}", err),
    }

    err = dev.close();
    match err {
        Error::NoError => println!("device close successful..."),
        _ => println!("dev close error - {:?}", err),
    }
}
<|endoftext|>


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

use app_units::Au;
use device::TextureFilter;
use euclid::{TypedPoint2D, UnknownUnit};
use fnv::FnvHasher;
use profiler::BackendProfileCounters;
use std::collections::{HashMap, HashSet};
use std::f32;
use std::hash::BuildHasherDefault;
use std::{i32, usize};
use std::path::PathBuf;
use std::sync::Arc;
use tiling;
use renderer::BlendMode;
use webrender_traits::{ClipId, ColorF, DeviceUintRect, Epoch, ExternalImageData, ExternalImageId};
use webrender_traits::{ImageData, ImageFormat, NativeFontHandle, PipelineId};

// An ID for a texture that is owned by the
// texture cache module. This can include atlases
// or standalone textures allocated via the
// texture cache (e.g. if an image is too large
// to be added to an atlas). The texture cache
// manages the allocation and freeing of these
// IDs, and the rendering thread maintains a
// map from cache texture ID to native texture.

#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct CacheTextureId(pub usize);

// Represents the source for a texture.
// These are passed from throughout the
// pipeline until they reach the rendering
// thread, where they are resolved to a
// native texture ID.

#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum SourceTexture {
    Invalid,
    TextureCache(CacheTextureId),
    External(ExternalImageData),
    #[cfg_attr(not(feature = "webgl"), allow(dead_code))]
    /// This is actually a gl::GLuint, with the shared texture id between the
    /// main context and the WebGL context.
    WebGL(u32),
}

const COLOR_FLOAT_TO_FIXED: f32 = 255.0;
pub const ANGLE_FLOAT_TO_FIXED: f32 = 65535.0;

pub const ORTHO_NEAR_PLANE: f32 = -1000000.0;
pub const ORTHO_FAR_PLANE: f32 = 1000000.0;

#[derive(Debug, PartialEq, Eq)]
pub enum TextureSampler {
    Color0,
    Color1,
    Color2,
    CacheA8,
    CacheRGBA8,
    Data32,
    ResourceCache,
    Layers,
    RenderTasks,
    Dither,
}

impl TextureSampler {
    pub fn color(n: usize) -> TextureSampler {
        match n {
            0 => TextureSampler::Color0,
            1 => TextureSampler::Color1,
            2 => TextureSampler::Color2,
            _ => {
                panic!("There are only 3 color samplers.");
            }
        }
    }
}

/// Optional textures that can be used as a source in the shaders.
/// Textures that are not used by the batch are equal to TextureId::invalid().
#[derive(Copy, Clone, Debug)]
pub struct BatchTextures {
    pub colors: [SourceTexture; 3],
}

impl BatchTextures {
    pub fn no_texture() -> Self {
        BatchTextures {
            colors: [SourceTexture::Invalid; 3],
        }
    }
}

// In some places we need to temporarily bind a texture to any slot.
pub const DEFAULT_TEXTURE: TextureSampler = TextureSampler::Color0;

#[derive(Clone, Copy, Debug)]
pub enum VertexAttribute {
    // vertex-frequency basic attributes
    Position,
    Color,
    ColorTexCoord,
    // instance-frequency primitive attributes
    Data0,
    Data1,
}

#[derive(Clone, Copy, Debug)]
pub enum BlurAttribute {
    // vertex frequency
    Position,
    // instance frequency
    RenderTaskIndex,
    SourceTaskIndex,
    Direction,
}

#[derive(Clone, Copy, Debug)]
pub enum ClipAttribute {
    // vertex frequency
    Position,
    // instance frequency
    RenderTaskIndex,
    LayerIndex,
    DataIndex,
    SegmentIndex,
    ResourceAddress,
}

// A packed RGBA8 color ordered for vertex data or similar.

#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct PackedColor {
    pub r: u8,
    pub g: u8,
    pub b: u8,
    pub a: u8,
}

impl PackedColor {
    pub fn from_color(color: &ColorF) -> PackedColor {
        PackedColor {
            r: (0.5 + color.r * COLOR_FLOAT_TO_FIXED).floor() as u8,
            g: (0.5 + color.g * COLOR_FLOAT_TO_FIXED).floor() as u8,
            b: (0.5 + color.b * COLOR_FLOAT_TO_FIXED).floor() as u8,
            a: (0.5 + color.a * COLOR_FLOAT_TO_FIXED).floor() as u8,
        }
    }
}

#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct PackedVertex {
    pub pos: [f32; 2],
}

#[derive(Debug)]
#[repr(C)]
pub struct DebugFontVertex {
    pub x: f32,
    pub y: f32,
    pub color: PackedColor,
    pub u: f32,
    pub v: f32,
}

impl DebugFontVertex {
    pub fn new(x: f32, y: f32, u: f32, v: f32, color: PackedColor) -> DebugFontVertex {
        DebugFontVertex {
            x: x,
            y: y,
            color: color,
            u: u,
            v: v,
        }
    }
}

#[repr(C)]
pub struct DebugColorVertex {
    pub x: f32,
    pub y: f32,
    pub color: PackedColor,
}

impl DebugColorVertex {
    pub fn new(x: f32, y: f32, color: PackedColor) -> DebugColorVertex {
        DebugColorVertex {
            x: x,
            y: y,
            color: color,
        }
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum RenderTargetMode {
    None,
    SimpleRenderTarget,
    LayerRenderTarget(i32),      // Number of texture layers
}

pub enum TextureUpdateOp {
    Create {
      width: u32,
      height: u32,
      format: ImageFormat,
      filter: TextureFilter,
      mode: RenderTargetMode,
      data: Option<ImageData>,
    },
    Update {
        page_pos_x: u32,    // the texture page position which we want to upload
        page_pos_y: u32,
        width: u32,
        height: u32,
        data: Arc<Vec<u8>>,
        stride: Option<u32>,
        offset: u32,
    },
    UpdateForExternalBuffer {
        rect: DeviceUintRect,
        id: ExternalImageId,
        channel_index: u8,
        stride: Option<u32>,
        offset: u32,
    },
    Grow {
        width: u32,
        height: u32,
        format: ImageFormat,
        filter: TextureFilter,
        mode: RenderTargetMode,
    },
    Free,
}

pub struct TextureUpdate {
    pub id: CacheTextureId,
    pub op: TextureUpdateOp,
}

pub struct TextureUpdateList {
    pub updates: Vec<TextureUpdate>,
}

impl TextureUpdateList {
    pub fn new() -> TextureUpdateList {
        TextureUpdateList {
            updates: Vec::new(),
        }
    }

    #[inline]
    pub fn push(&mut self, update: TextureUpdate) {
        self.updates.push(update);
    }
}

/// Mostly wraps a tiling::Frame, adding a bit of extra information.
pub struct RendererFrame {
    /// The last rendered epoch for each pipeline present in the frame.
    /// This information is used to know if a certain transformation on the layout has
    /// been rendered, which is necessary for reftests.
    pub pipeline_epoch_map: HashMap<PipelineId, Epoch, BuildHasherDefault<FnvHasher>>,
    /// The layers that are currently affected by the over-scrolling animation.
    pub layers_bouncing_back: HashSet<ClipId, BuildHasherDefault<FnvHasher>>,

    pub frame: Option<tiling::Frame>,
}

impl RendererFrame {
    pub fn new(pipeline_epoch_map: HashMap<PipelineId, Epoch, BuildHasherDefault<FnvHasher>>,
               layers_bouncing_back: HashSet<ClipId, BuildHasherDefault<FnvHasher>>,
               frame: Option<tiling::Frame>)
               -> RendererFrame {
        RendererFrame {
            pipeline_epoch_map: pipeline_epoch_map,
            layers_bouncing_back: layers_bouncing_back,
            frame: frame,
        }
    }
}

pub enum ResultMsg {
    RefreshShader(PathBuf),
    NewFrame(RendererFrame, TextureUpdateList, BackendProfileCounters),
}

#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AxisDirection {
    Horizontal,
    Vertical,
}

#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
pub struct StackingContextIndex(pub usize);

#[derive(Clone, Copy, Debug)]
pub struct RectUv<T, U = UnknownUnit> {
    pub top_left: TypedPoint2D<T, U>,
    pub top_right: TypedPoint2D<T, U>,
    pub bottom_left: TypedPoint2D<T, U>,
    pub bottom_right: TypedPoint2D<T, U>,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum LowLevelFilterOp {
    Blur(Au, AxisDirection),
    Brightness(Au),
    Contrast(Au),
    Grayscale(Au),
    /// Fixed-point in `ANGLE_FLOAT_TO_FIXED` units.
    HueRotate(i32),
    Invert(Au),
    Opacity(Au),
    Saturate(Au),
    Sepia(Au),
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum HardwareCompositeOp {
    PremultipliedAlpha,
}

impl HardwareCompositeOp {
    pub fn to_blend_mode(&self) -> BlendMode {
        match *self {
            HardwareCompositeOp::PremultipliedAlpha => BlendMode::PremultipliedAlpha,
        }
    }
}
<commit_msg>Auto merge of #1385 - staktrace:unused_import, r=kvark<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use app_units::Au;
use device::TextureFilter;
use euclid::{TypedPoint2D, UnknownUnit};
use fnv::FnvHasher;
use profiler::BackendProfileCounters;
use std::collections::{HashMap, HashSet};
use std::f32;
use std::hash::BuildHasherDefault;
use std::{i32, usize};
use std::path::PathBuf;
use std::sync::Arc;
use tiling;
use renderer::BlendMode;
use webrender_traits::{ClipId, ColorF, DeviceUintRect, Epoch, ExternalImageData, ExternalImageId};
use webrender_traits::{ImageData, ImageFormat, PipelineId};

// An ID for a texture that is owned by the
// texture cache module. This can include atlases
// or standalone textures allocated via the
// texture cache (e.g. if an image is too large
// to be added to an atlas). The texture cache
// manages the allocation and freeing of these
// IDs, and the rendering thread maintains a
// map from cache texture ID to native texture.

#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct CacheTextureId(pub usize);

// Represents the source for a texture.
// These are passed from throughout the
// pipeline until they reach the rendering
// thread, where they are resolved to a
// native texture ID.

#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum SourceTexture {
    Invalid,
    TextureCache(CacheTextureId),
    External(ExternalImageData),
    #[cfg_attr(not(feature = "webgl"), allow(dead_code))]
    /// This is actually a gl::GLuint, with the shared texture id between the
    /// main context and the WebGL context.
    WebGL(u32),
}

const COLOR_FLOAT_TO_FIXED: f32 = 255.0;
pub const ANGLE_FLOAT_TO_FIXED: f32 = 65535.0;

pub const ORTHO_NEAR_PLANE: f32 = -1000000.0;
pub const ORTHO_FAR_PLANE: f32 = 1000000.0;

#[derive(Debug, PartialEq, Eq)]
pub enum TextureSampler {
    Color0,
    Color1,
    Color2,
    CacheA8,
    CacheRGBA8,
    Data32,
    ResourceCache,
    Layers,
    RenderTasks,
    Dither,
}

impl TextureSampler {
    pub fn color(n: usize) -> TextureSampler {
        match n {
            0 => TextureSampler::Color0,
            1 => TextureSampler::Color1,
            2 => TextureSampler::Color2,
            _ => {
                panic!("There are only 3 color samplers.");
            }
        }
    }
}

/// Optional textures that can be used as a source in the shaders.
/// Textures that are not used by the batch are equal to TextureId::invalid().
#[derive(Copy, Clone, Debug)]
pub struct BatchTextures {
    pub colors: [SourceTexture; 3],
}

impl BatchTextures {
    pub fn no_texture() -> Self {
        BatchTextures {
            colors: [SourceTexture::Invalid; 3],
        }
    }
}

// In some places we need to temporarily bind a texture to any slot.
pub const DEFAULT_TEXTURE: TextureSampler = TextureSampler::Color0;

#[derive(Clone, Copy, Debug)]
pub enum VertexAttribute {
    // vertex-frequency basic attributes
    Position,
    Color,
    ColorTexCoord,
    // instance-frequency primitive attributes
    Data0,
    Data1,
}

#[derive(Clone, Copy, Debug)]
pub enum BlurAttribute {
    // vertex frequency
    Position,
    // instance frequency
    RenderTaskIndex,
    SourceTaskIndex,
    Direction,
}

#[derive(Clone, Copy, Debug)]
pub enum ClipAttribute {
    // vertex frequency
    Position,
    // instance frequency
    RenderTaskIndex,
    LayerIndex,
    DataIndex,
    SegmentIndex,
    ResourceAddress,
}

// A packed RGBA8 color ordered for vertex data or similar.

#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct PackedColor {
    pub r: u8,
    pub g: u8,
    pub b: u8,
    pub a: u8,
}

impl PackedColor {
    pub fn from_color(color: &ColorF) -> PackedColor {
        PackedColor {
            r: (0.5 + color.r * COLOR_FLOAT_TO_FIXED).floor() as u8,
            g: (0.5 + color.g * COLOR_FLOAT_TO_FIXED).floor() as u8,
            b: (0.5 + color.b * COLOR_FLOAT_TO_FIXED).floor() as u8,
            a: (0.5 + color.a * COLOR_FLOAT_TO_FIXED).floor() as u8,
        }
    }
}

#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct PackedVertex {
    pub pos: [f32; 2],
}

#[derive(Debug)]
#[repr(C)]
pub struct DebugFontVertex {
    pub x: f32,
    pub y: f32,
    pub color: PackedColor,
    pub u: f32,
    pub v: f32,
}

impl DebugFontVertex {
    pub fn new(x: f32, y: f32, u: f32, v: f32, color: PackedColor) -> DebugFontVertex {
        DebugFontVertex {
            x: x,
            y: y,
            color: color,
            u: u,
            v: v,
        }
    }
}

#[repr(C)]
pub struct DebugColorVertex {
    pub x: f32,
    pub y: f32,
    pub color: PackedColor,
}

impl DebugColorVertex {
    pub fn new(x: f32, y: f32, color: PackedColor) -> DebugColorVertex {
        DebugColorVertex {
            x: x,
            y: y,
            color: color,
        }
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum RenderTargetMode {
    None,
    SimpleRenderTarget,
    LayerRenderTarget(i32),      // Number of texture layers
}

pub enum TextureUpdateOp {
    Create {
      width: u32,
      height: u32,
      format: ImageFormat,
      filter: TextureFilter,
      mode: RenderTargetMode,
      data: Option<ImageData>,
    },
    Update {
        page_pos_x: u32,    // the texture page position which we want to upload
        page_pos_y: u32,
        width: u32,
        height: u32,
        data: Arc<Vec<u8>>,
        stride: Option<u32>,
        offset: u32,
    },
    UpdateForExternalBuffer {
        rect: DeviceUintRect,
        id: ExternalImageId,
        channel_index: u8,
        stride: Option<u32>,
        offset: u32,
    },
    Grow {
        width: u32,
        height: u32,
        format: ImageFormat,
        filter: TextureFilter,
        mode: RenderTargetMode,
    },
    Free,
}

pub struct TextureUpdate {
    pub id: CacheTextureId,
    pub op: TextureUpdateOp,
}

pub struct TextureUpdateList {
    pub updates: Vec<TextureUpdate>,
}

impl TextureUpdateList {
    pub fn new() -> TextureUpdateList {
        TextureUpdateList {
            updates: Vec::new(),
        }
    }

    #[inline]
    pub fn push(&mut self, update: TextureUpdate) {
        self.updates.push(update);
    }
}

/// Mostly wraps a tiling::Frame, adding a bit of extra information.
pub struct RendererFrame {
    /// The last rendered epoch for each pipeline present in the frame.
    /// This information is used to know if a certain transformation on the layout has
    /// been rendered, which is necessary for reftests.
    pub pipeline_epoch_map: HashMap<PipelineId, Epoch, BuildHasherDefault<FnvHasher>>,
    /// The layers that are currently affected by the over-scrolling animation.
    pub layers_bouncing_back: HashSet<ClipId, BuildHasherDefault<FnvHasher>>,

    pub frame: Option<tiling::Frame>,
}

impl RendererFrame {
    pub fn new(pipeline_epoch_map: HashMap<PipelineId, Epoch, BuildHasherDefault<FnvHasher>>,
               layers_bouncing_back: HashSet<ClipId, BuildHasherDefault<FnvHasher>>,
               frame: Option<tiling::Frame>)
               -> RendererFrame {
        RendererFrame {
            pipeline_epoch_map: pipeline_epoch_map,
            layers_bouncing_back: layers_bouncing_back,
            frame: frame,
        }
    }
}

pub enum ResultMsg {
    RefreshShader(PathBuf),
    NewFrame(RendererFrame, TextureUpdateList, BackendProfileCounters),
}

#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AxisDirection {
    Horizontal,
    Vertical,
}

#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
pub struct StackingContextIndex(pub usize);

#[derive(Clone, Copy, Debug)]
pub struct RectUv<T, U = UnknownUnit> {
    pub top_left: TypedPoint2D<T, U>,
    pub top_right: TypedPoint2D<T, U>,
    pub bottom_left: TypedPoint2D<T, U>,
    pub bottom_right: TypedPoint2D<T, U>,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum LowLevelFilterOp {
    Blur(Au, AxisDirection),
    Brightness(Au),
    Contrast(Au),
    Grayscale(Au),
    /// Fixed-point in `ANGLE_FLOAT_TO_FIXED` units.
    HueRotate(i32),
    Invert(Au),
    Opacity(Au),
    Saturate(Au),
    Sepia(Au),
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum HardwareCompositeOp {
    PremultipliedAlpha,
}

impl HardwareCompositeOp {
    pub fn to_blend_mode(&self) -> BlendMode {
        match *self {
            HardwareCompositeOp::PremultipliedAlpha => BlendMode::PremultipliedAlpha,
        }
    }
}
<|endoftext|>


<commit_before>use crate::thread::Time;
use crate::*;
use rustc_target::abi::{Align, Size};
use std::time::{Instant, SystemTime};

/// Implementation of the SYS_futex syscall.
pub fn futex<'tcx>(
    this: &mut MiriEvalContext<'_, 'tcx>,
    args: &[OpTy<'tcx, Tag>],
    dest: &PlaceTy<'tcx, Tag>,
) -> InterpResult<'tcx> {
    // The amount of arguments used depends on the type of futex operation.
    // The full futex syscall takes six arguments (excluding the syscall
    // number), which is also the maximum amount of arguments a linux syscall
    // can take on most architectures.
    // However, not all futex operations use all six arguments. The unused ones
    // may or may not be left out from the `syscall()` call.
    // Therefore we don't use `check_arg_count` here, but only check for the
    // number of arguments to fall within a range.
    if args.len() < 4 {
        throw_ub_format!(
            "incorrect number of arguments for `futex` syscall: got {}, expected at least 4",
            args.len()
        );
    }

    // The first three arguments (after the syscall number itself) are the same to all futex operations:
    //     (int *addr, int op, int val).
    // We checked above that these definitely exist.
    let addr = this.read_immediate(&args[1])?;
    let op = this.read_scalar(&args[2])?.to_i32()?;
    let val = this.read_scalar(&args[3])?.to_i32()?;

    let thread = this.get_active_thread();
    let addr_scalar = addr.to_scalar()?;

    let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG")?;
    let futex_wait = this.eval_libc_i32("FUTEX_WAIT")?;
    let futex_wake = this.eval_libc_i32("FUTEX_WAKE")?;
    let futex_realtime = this.eval_libc_i32("FUTEX_CLOCK_REALTIME")?;

    // FUTEX_PRIVATE enables an optimization that stops it from working across processes.
    // Miri doesn't support that anyway, so we ignore that flag.
    match op & !futex_private {
        // FUTEX_WAIT: (int *addr, int op = FUTEX_WAIT, int val, const timespec *timeout)
        // Blocks the thread if *addr still equals val. Wakes up when FUTEX_WAKE is called on the same address,
        // or *timeout expires. `timeout == null` for an infinite timeout.
        op if op & !futex_realtime == futex_wait => {
            if args.len() < 5 {
                throw_ub_format!(
                    "incorrect number of arguments for `futex` syscall with `op=FUTEX_WAIT`: got {}, expected at least 5",
                    args.len()
                );
            }

            // `deref_operand` but not actually dereferencing the ptr yet (it might be NULL!).
            let timeout = this.ref_to_mplace(&this.read_immediate(&args[4])?)?;
            let timeout_time = if this.ptr_is_null(timeout.ptr)? {
                None
            } else {
                this.check_no_isolation(
                    "`futex` syscall with `op=FUTEX_WAIT` and non-null timeout",
                )?;
                let duration = match this.read_timespec(&timeout)? {
                    Some(duration) => duration,
                    None => {
                        let einval = this.eval_libc("EINVAL")?;
                        this.set_last_error(einval)?;
                        this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
                        return Ok(());
                    }
                };
                Some(if op & futex_realtime != 0 {
                    Time::RealTime(SystemTime::now().checked_add(duration).unwrap())
                } else {
                    Time::Monotonic(Instant::now().checked_add(duration).unwrap())
                })
            };
            // Check the pointer for alignment and validity.
            // The API requires `addr` to be a 4-byte aligned pointer, and will
            // use the 4 bytes at the given address as an (atomic) i32.
            this.check_ptr_access_align(
                this.scalar_to_ptr(addr_scalar),
                Size::from_bytes(4),
                Align::from_bytes(4).unwrap(),
                CheckInAllocMsg::MemoryAccessTest,
            )?;
            // Read an `i32` through the pointer, regardless of any wrapper types.
            // It's not uncommon for `addr` to be passed as another type than `*mut i32`, such as `*const AtomicI32`.
            // FIXME: this fails if `addr` is not a pointer type.
            // The atomic ordering for futex(https://man7.org/linux/man-pages/man2/futex.2.html):
            //  "The load of the value of the futex word is an
            //   atomic memory access (i.e., using atomic machine instructions
            //   of the respective architecture).  This load, the comparison
            //   with the expected value, and starting to sleep are performed
            //   atomically and totally ordered with respect to other futex
            //   operations on the same futex word."
            // SeqCst is total order over all operations.
            // FIXME: check if this should be changed when weak memory orders are added.
            let futex_val = this
                .read_scalar_at_offset_atomic(
                    &addr.into(),
                    0,
                    this.machine.layouts.i32,
                    AtomicReadOp::SeqCst,
                )?
                .to_i32()?;
            if val == futex_val {
                // The value still matches, so we block the trait make it wait for FUTEX_WAKE.
                this.block_thread(thread);
                this.futex_wait(addr_scalar.to_machine_usize(this)?, thread);
                // Succesfully waking up from FUTEX_WAIT always returns zero.
                this.write_scalar(Scalar::from_machine_isize(0, this), dest)?;
                // Register a timeout callback if a timeout was specified.
                // This callback will override the return value when the timeout triggers.
                let dest = *dest;
                if let Some(timeout_time) = timeout_time {
                    this.register_timeout_callback(
                        thread,
                        timeout_time,
                        Box::new(move |this| {
                            this.unblock_thread(thread);
                            this.futex_remove_waiter(addr_scalar.to_machine_usize(this)?, thread);
                            let etimedout = this.eval_libc("ETIMEDOUT")?;
                            this.set_last_error(etimedout)?;
                            this.write_scalar(Scalar::from_machine_isize(-1, this), &dest)?;
                            Ok(())
                        }),
                    );
                }
            } else {
                // The futex value doesn't match the expected value, so we return failure
                // right away without sleeping: -1 and errno set to EAGAIN.
                let eagain = this.eval_libc("EAGAIN")?;
                this.set_last_error(eagain)?;
                this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
            }
        }
        // FUTEX_WAKE: (int *addr, int op = FUTEX_WAKE, int val)
        // Wakes at most `val` threads waiting on the futex at `addr`.
        // Returns the amount of threads woken up.
        // Does not access the futex value at *addr.
        op if op == futex_wake => {
            let mut n = 0;
            for _ in 0..val {
                if let Some(thread) = this.futex_wake(addr_scalar.to_machine_usize(this)?) {
                    this.unblock_thread(thread);
                    this.unregister_timeout_callback_if_exists(thread);
                    n += 1;
                } else {
                    break;
                }
            }
            this.write_scalar(Scalar::from_machine_isize(n, this), dest)?;
        }
        op => throw_unsup_format!("Miri does not support `futex` syscall with op={}", op),
    }

    Ok(())
}
<commit_msg>Add support for FUTEX_WAIT_BITSET(bitset=MAX).<commit_after>use crate::thread::Time;
use crate::*;
use rustc_target::abi::{Align, Size};
use std::time::{Instant, SystemTime};

/// Implementation of the SYS_futex syscall.
pub fn futex<'tcx>(
    this: &mut MiriEvalContext<'_, 'tcx>,
    args: &[OpTy<'tcx, Tag>],
    dest: &PlaceTy<'tcx, Tag>,
) -> InterpResult<'tcx> {
    // The amount of arguments used depends on the type of futex operation.
    // The full futex syscall takes six arguments (excluding the syscall
    // number), which is also the maximum amount of arguments a linux syscall
    // can take on most architectures.
    // However, not all futex operations use all six arguments. The unused ones
    // may or may not be left out from the `syscall()` call.
    // Therefore we don't use `check_arg_count` here, but only check for the
    // number of arguments to fall within a range.
    if args.len() < 4 {
        throw_ub_format!(
            "incorrect number of arguments for `futex` syscall: got {}, expected at least 4",
            args.len()
        );
    }

    // The first three arguments (after the syscall number itself) are the same to all futex operations:
    //     (int *addr, int op, int val).
    // We checked above that these definitely exist.
    let addr = this.read_immediate(&args[1])?;
    let op = this.read_scalar(&args[2])?.to_i32()?;
    let val = this.read_scalar(&args[3])?.to_i32()?;

    let thread = this.get_active_thread();
    let addr_scalar = addr.to_scalar()?;

    let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG")?;
    let futex_wait = this.eval_libc_i32("FUTEX_WAIT")?;
    let futex_wait_bitset = this.eval_libc_i32("FUTEX_WAIT_BITSET")?;
    let futex_wake = this.eval_libc_i32("FUTEX_WAKE")?;
    let futex_realtime = this.eval_libc_i32("FUTEX_CLOCK_REALTIME")?;

    // FUTEX_PRIVATE enables an optimization that stops it from working across processes.
    // Miri doesn't support that anyway, so we ignore that flag.
    match op & !futex_private {
        // FUTEX_WAIT: (int *addr, int op = FUTEX_WAIT, int val, const timespec *timeout)
        // Blocks the thread if *addr still equals val. Wakes up when FUTEX_WAKE is called on the same address,
        // or *timeout expires. `timeout == null` for an infinite timeout.
        //
        // FUTEX_WAIT_BITSET: (int *addr, int op = FUTEX_WAIT_BITSET, int val, const timespec *timeout, int *_ignored, unsigned int bitset)
        // When bitset is u32::MAX, this is identical to FUTEX_WAIT, except the timeout is absolute rather than relative.
        op if op & !futex_realtime == futex_wait || op & !futex_realtime == futex_wait_bitset => {
            let wait_bitset = op & !futex_realtime == futex_wait_bitset;

            if wait_bitset {
                if args.len() != 7 {
                    throw_ub_format!(
                        "incorrect number of arguments for `futex` syscall with `op=FUTEX_WAIT_BITSET`: got {}, expected 7",
                        args.len()
                    );
                }

                let bitset = this.read_scalar(&args[6])?.to_u32()?;

                if bitset != u32::MAX {
                    throw_unsup_format!("Miri does not support `futex` syscall with `op=FUTEX_WAIT_BITSET` with a bitset other than UINT_MAX");
                }
            } else {
                if args.len() < 5 {
                    throw_ub_format!(
                        "incorrect number of arguments for `futex` syscall with `op=FUTEX_WAIT`: got {}, expected at least 5",
                        args.len()
                    );
                }
            }

            // `deref_operand` but not actually dereferencing the ptr yet (it might be NULL!).
            let timeout = this.ref_to_mplace(&this.read_immediate(&args[4])?)?;
            let timeout_time = if this.ptr_is_null(timeout.ptr)? {
                None
            } else {
                this.check_no_isolation(
                    "`futex` syscall with `op=FUTEX_WAIT` and non-null timeout",
                )?;
                let duration = match this.read_timespec(&timeout)? {
                    Some(duration) => duration,
                    None => {
                        let einval = this.eval_libc("EINVAL")?;
                        this.set_last_error(einval)?;
                        this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
                        return Ok(());
                    }
                };
                Some(if wait_bitset {
                    // FUTEX_WAIT_BITSET uses an absolute timestamp.
                    if op & futex_realtime != 0 {
                        Time::RealTime(SystemTime::UNIX_EPOCH.checked_add(duration).unwrap())
                    } else {
                        Time::Monotonic(this.machine.time_anchor.checked_add(duration).unwrap())
                    }
                } else {
                    // FUTEX_WAIT uses a relative timestamp.
                    if op & futex_realtime != 0 {
                        Time::RealTime(SystemTime::now().checked_add(duration).unwrap())
                    } else {
                        Time::Monotonic(Instant::now().checked_add(duration).unwrap())
                    }
                })
            };
            // Check the pointer for alignment and validity.
            // The API requires `addr` to be a 4-byte aligned pointer, and will
            // use the 4 bytes at the given address as an (atomic) i32.
            this.check_ptr_access_align(
                this.scalar_to_ptr(addr_scalar),
                Size::from_bytes(4),
                Align::from_bytes(4).unwrap(),
                CheckInAllocMsg::MemoryAccessTest,
            )?;
            // Read an `i32` through the pointer, regardless of any wrapper types.
            // It's not uncommon for `addr` to be passed as another type than `*mut i32`, such as `*const AtomicI32`.
            // FIXME: this fails if `addr` is not a pointer type.
            // The atomic ordering for futex(https://man7.org/linux/man-pages/man2/futex.2.html):
            //  "The load of the value of the futex word is an
            //   atomic memory access (i.e., using atomic machine instructions
            //   of the respective architecture).  This load, the comparison
            //   with the expected value, and starting to sleep are performed
            //   atomically and totally ordered with respect to other futex
            //   operations on the same futex word."
            // SeqCst is total order over all operations.
            // FIXME: check if this should be changed when weak memory orders are added.
            let futex_val = this
                .read_scalar_at_offset_atomic(
                    &addr.into(),
                    0,
                    this.machine.layouts.i32,
                    AtomicReadOp::SeqCst,
                )?
                .to_i32()?;
            if val == futex_val {
                // The value still matches, so we block the trait make it wait for FUTEX_WAKE.
                this.block_thread(thread);
                this.futex_wait(addr_scalar.to_machine_usize(this)?, thread);
                // Succesfully waking up from FUTEX_WAIT always returns zero.
                this.write_scalar(Scalar::from_machine_isize(0, this), dest)?;
                // Register a timeout callback if a timeout was specified.
                // This callback will override the return value when the timeout triggers.
                let dest = *dest;
                if let Some(timeout_time) = timeout_time {
                    this.register_timeout_callback(
                        thread,
                        timeout_time,
                        Box::new(move |this| {
                            this.unblock_thread(thread);
                            this.futex_remove_waiter(addr_scalar.to_machine_usize(this)?, thread);
                            let etimedout = this.eval_libc("ETIMEDOUT")?;
                            this.set_last_error(etimedout)?;
                            this.write_scalar(Scalar::from_machine_isize(-1, this), &dest)?;
                            Ok(())
                        }),
                    );
                }
            } else {
                // The futex value doesn't match the expected value, so we return failure
                // right away without sleeping: -1 and errno set to EAGAIN.
                let eagain = this.eval_libc("EAGAIN")?;
                this.set_last_error(eagain)?;
                this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
            }
        }
        // FUTEX_WAKE: (int *addr, int op = FUTEX_WAKE, int val)
        // Wakes at most `val` threads waiting on the futex at `addr`.
        // Returns the amount of threads woken up.
        // Does not access the futex value at *addr.
        op if op == futex_wake => {
            let mut n = 0;
            for _ in 0..val {
                if let Some(thread) = this.futex_wake(addr_scalar.to_machine_usize(this)?) {
                    this.unblock_thread(thread);
                    this.unregister_timeout_callback_if_exists(thread);
                    n += 1;
                } else {
                    break;
                }
            }
            this.write_scalar(Scalar::from_machine_isize(n, this), dest)?;
        }
        op => throw_unsup_format!("Miri does not support `futex` syscall with op={}", op),
    }

    Ok(())
}
<|endoftext|>


<commit_before>use crate::consts::{constant, Constant};
use crate::utils::paths;
use crate::utils::{is_direct_expn_of, is_expn_of, match_def_path, span_help_and_lint, snippet};
use if_chain::if_chain;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use syntax::ast::LitKind;
use std::borrow::Cow;

declare_clippy_lint! {
    /// **What it does:** Checks for `assert!(true)` and `assert!(false)` calls.
    ///
    /// **Why is this bad?** Will be optimized out by the compiler or should probably be replaced by a
    /// panic!() or unreachable!()
    ///
    /// **Known problems:** None
    ///
    /// **Example:**
    /// ```rust,ignore
    /// assert!(false)
    /// // or
    /// assert!(true)
    /// // or
    /// const B: bool = false;
    /// assert!(B)
    /// ```
    pub ASSERTIONS_ON_CONSTANTS,
    style,
    "`assert!(true)` / `assert!(false)` will be optimized out by the compiler, and should probably be replaced by a `panic!()` or `unreachable!()`"
}

declare_lint_pass!(AssertionsOnConstants => [ASSERTIONS_ON_CONSTANTS]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        let lint_assert_cb = |is_debug_assert: bool| {
            if let ExprKind::Unary(_, ref lit) = e.kind {
                if let Some((Constant::Bool(is_true), _)) = constant(cx, cx.tables, lit) {
                    if is_true {
                        span_help_and_lint(
                            cx,
                            ASSERTIONS_ON_CONSTANTS,
                            e.span,
                            "`assert!(true)` will be optimized out by the compiler",
                            "remove it",
                        );
                    } else if !is_debug_assert {
                        span_help_and_lint(
                            cx,
                            ASSERTIONS_ON_CONSTANTS,
                            e.span,
                            "`assert!(false)` should probably be replaced",
                            "use `panic!()` or `unreachable!()`",
                        );
                    }
                }
            }
        };
        if let Some(debug_assert_span) = is_expn_of(e.span, "debug_assert") {
            if debug_assert_span.from_expansion() {
                return;
            }
            lint_assert_cb(true);
        } else if let Some(assert_span) = is_direct_expn_of(e.span, "assert") {
            if assert_span.from_expansion() {
                return;
            }
            if let Some((panic_message, is_true)) = assert_with_message(&cx, e) {
                if is_true {
                    span_help_and_lint(
                        cx,
                        ASSERTIONS_ON_CONSTANTS,
                        e.span,
                        "`assert!(true)` will be optimized out by the compiler",
                        "remove it",
                    );
                } else if panic_message.is_empty() || panic_message.starts_with("\"assertion failed: ") {
                    span_help_and_lint(
                        cx,
                        ASSERTIONS_ON_CONSTANTS,
                        e.span,
                        "`assert!(false)` should probably be replaced",
                        "use `panic!()` or `unreachable!()`",
                    );
                } else {
                    span_help_and_lint(
                        cx,
                        ASSERTIONS_ON_CONSTANTS,
                        e.span,
                        &format!("`assert!(false, {})` should probably be replaced", panic_message,),
                        &format!(
                            "use `panic!({})` or `unreachable!({})`",
                            panic_message, panic_message,
                        ),
                    );
                }
            }
        }
    }
}

/// Check if the expression matches
///
/// ```rust,ignore
/// match { let _t = !c; _t } {
///     true => {
///         {
///             ::std::rt::begin_panic(message, _)
///         }
///     }
///     _ => { }
/// };
/// ```
///
/// where `message` is a string literal and `c` is a constant bool.
///
/// TODO extend this to match anything as message not just string literals
///
/// Returns the `message` argument of `begin_panic` and the value of `c` which is the
/// first argument of `assert!`.
fn assert_with_message<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> Option<(Cow<'a, str>, bool)> {
    if_chain! {
        if let ExprKind::Match(ref expr, ref arms, _) = expr.kind;
        // matches { let _t = expr; _t }
        if let ExprKind::DropTemps(ref expr) = expr.kind;
        if let ExprKind::Unary(UnOp::UnNot, ref expr) = expr.kind;
        // bind the first argument of the `assert!` macro
        if let Some((Constant::Bool(is_true), _)) = constant(cx, cx.tables, expr);
        // arm 1 pattern
        if let PatKind::Lit(ref lit_expr) = arms[0].pat.kind;
        if let ExprKind::Lit(ref lit) = lit_expr.kind;
        if let LitKind::Bool(true) = lit.node;
        // arm 1 block
        if let ExprKind::Block(ref block, _) = arms[0].body.kind;
        if block.stmts.len() == 0;
        if let Some(block_expr) = &block.expr;
        if let ExprKind::Block(ref inner_block, _) = block_expr.kind;
        if let Some(begin_panic_call) = &inner_block.expr;
        // function call
        if let Some(args) = match_function_call(cx, begin_panic_call, &paths::BEGIN_PANIC);
        if args.len() == 2;
        // bind the second argument of the `assert!` macro
        let panic_message_arg = snippet(cx, args[0].span, "..");
        // second argument of begin_panic is irrelevant
        // as is the second match arm
        then {
            return Some((panic_message_arg, is_true));
        }
    }
    None
}

/// Matches a function call with the given path and returns the arguments.
///
/// Usage:
///
/// ```rust,ignore
/// if let Some(args) = match_function_call(cx, begin_panic_call, &paths::BEGIN_PANIC);
/// ```
fn match_function_call<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, path: &[&str]) -> Option<&'a [Expr]> {
    if_chain! {
        if let ExprKind::Call(ref fun, ref args) = expr.kind;
        if let ExprKind::Path(ref qpath) = fun.kind;
        if let Some(fun_def_id) = cx.tables.qpath_res(qpath, fun.hir_id).opt_def_id();
        if match_def_path(cx, fun_def_id, path);
        then {
            return Some(&args)
        }
    };
    None
}
<commit_msg>Reduce duplication<commit_after>use crate::consts::{constant, Constant};
use crate::utils::paths;
use crate::utils::{is_direct_expn_of, is_expn_of, match_def_path, snippet_opt, span_help_and_lint};
use if_chain::if_chain;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use syntax::ast::LitKind;

declare_clippy_lint! {
    /// **What it does:** Checks for `assert!(true)` and `assert!(false)` calls.
    ///
    /// **Why is this bad?** Will be optimized out by the compiler or should probably be replaced by a
    /// panic!() or unreachable!()
    ///
    /// **Known problems:** None
    ///
    /// **Example:**
    /// ```rust,ignore
    /// assert!(false)
    /// // or
    /// assert!(true)
    /// // or
    /// const B: bool = false;
    /// assert!(B)
    /// ```
    pub ASSERTIONS_ON_CONSTANTS,
    style,
    "`assert!(true)` / `assert!(false)` will be optimized out by the compiler, and should probably be replaced by a `panic!()` or `unreachable!()`"
}

declare_lint_pass!(AssertionsOnConstants => [ASSERTIONS_ON_CONSTANTS]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        let lint_true = || {
            span_help_and_lint(
                cx,
                ASSERTIONS_ON_CONSTANTS,
                e.span,
                "`assert!(true)` will be optimized out by the compiler",
                "remove it",
            );
        };
        let lint_false_without_message = || {
            span_help_and_lint(
                cx,
                ASSERTIONS_ON_CONSTANTS,
                e.span,
                "`assert!(false)` should probably be replaced",
                "use `panic!()` or `unreachable!()`",
            );
        };
        let lint_false_with_message = |panic_message: String| {
            span_help_and_lint(
                cx,
                ASSERTIONS_ON_CONSTANTS,
                e.span,
                &format!("`assert!(false, {})` should probably be replaced", panic_message),
                &format!("use `panic!({})` or `unreachable!({})`", panic_message, panic_message),
            )
        };

        if let Some(debug_assert_span) = is_expn_of(e.span, "debug_assert") {
            if debug_assert_span.from_expansion() {
                return;
            }
            if_chain! {
                if let ExprKind::Unary(_, ref lit) = e.kind;
                if let Some((Constant::Bool(is_true), _)) = constant(cx, cx.tables, lit);
                if is_true;
                then {
                    lint_true();
                }
            };
        } else if let Some(assert_span) = is_direct_expn_of(e.span, "assert") {
            if assert_span.from_expansion() {
                return;
            }
            if let Some(assert_match) = match_assert_with_message(&cx, e) {
                match assert_match {
                    // matched assert but not message
                    AssertKind::WithoutMessage(false) => lint_false_without_message(),
                    AssertKind::WithoutMessage(true) | AssertKind::WithMessage(_, true) => lint_true(),
                    AssertKind::WithMessage(panic_message, false) => lint_false_with_message(panic_message),
                };
            }
        }
    }
}

/// Result of calling `match_assert_with_message`.
enum AssertKind {
    WithMessage(String, bool),
    WithoutMessage(bool),
}

/// Check if the expression matches
///
/// ```rust,ignore
/// match { let _t = !c; _t } {
///     true => {
///         {
///             ::std::rt::begin_panic(message, _)
///         }
///     }
///     _ => { }
/// };
/// ```
///
/// where `message` is any expression and `c` is a constant bool.
fn match_assert_with_message<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> Option<AssertKind> {
    if_chain! {
        if let ExprKind::Match(ref expr, ref arms, _) = expr.kind;
        // matches { let _t = expr; _t }
        if let ExprKind::DropTemps(ref expr) = expr.kind;
        if let ExprKind::Unary(UnOp::UnNot, ref expr) = expr.kind;
        // bind the first argument of the `assert!` macro
        if let Some((Constant::Bool(is_true), _)) = constant(cx, cx.tables, expr);
        // arm 1 pattern
        if let PatKind::Lit(ref lit_expr) = arms[0].pat.kind;
        if let ExprKind::Lit(ref lit) = lit_expr.kind;
        if let LitKind::Bool(true) = lit.node;
        // arm 1 block
        if let ExprKind::Block(ref block, _) = arms[0].body.kind;
        if block.stmts.len() == 0;
        if let Some(block_expr) = &block.expr;
        if let ExprKind::Block(ref inner_block, _) = block_expr.kind;
        if let Some(begin_panic_call) = &inner_block.expr;
        // function call
        if let Some(args) = match_function_call(cx, begin_panic_call, &paths::BEGIN_PANIC);
        if args.len() == 2;
        // bind the second argument of the `assert!` macro if it exists
        if let panic_message = snippet_opt(cx, args[0].span);
        // second argument of begin_panic is irrelevant
        // as is the second match arm
        then {
            // an empty message occurs when it was generated by the macro
            // (and not passed by the user)
            return panic_message
                .filter(|msg| !msg.is_empty())
                .map(|msg| AssertKind::WithMessage(msg, is_true))
                .or(Some(AssertKind::WithoutMessage(is_true)));
        }
    }
    None
}

/// Matches a function call with the given path and returns the arguments.
///
/// Usage:
///
/// ```rust,ignore
/// if let Some(args) = match_function_call(cx, begin_panic_call, &paths::BEGIN_PANIC);
/// ```
fn match_function_call<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, path: &[&str]) -> Option<&'a [Expr]> {
    if_chain! {
        if let ExprKind::Call(ref fun, ref args) = expr.kind;
        if let ExprKind::Path(ref qpath) = fun.kind;
        if let Some(fun_def_id) = cx.tables.qpath_res(qpath, fun.hir_id).opt_def_id();
        if match_def_path(cx, fun_def_id, path);
        then {
            return Some(&args)
        }
    };
    None
}
<|endoftext|>