<commit_before>//! This module provides a simplified abstraction for working with
//! code blocks identified by their integer `NodeId`. In particular,
//! it captures a common set of attributes that all "function-like
//! things" (represented by `FnLike` instances) share. For example,
//! all `FnLike` instances have a type signature (be it explicit or
//! inferred). And all `FnLike` instances have a body, i.e., the code
//! that is run when the function-like thing it represents is invoked.
//!
//! With the above abstraction in place, one can treat the program
//! text as a collection of blocks of code (and most such blocks are
//! nested within a uniquely determined `FnLike`), and users can ask
//! for the `Code` associated with a particular NodeId.

use crate::hir::map::Map;
use rustc_hir as hir;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{Expr, FnDecl, Node};
use rustc_span::symbol::Ident;
use rustc_span::Span;

/// An FnLikeNode is a Node that is like a fn, in that it has a decl
/// and a body (as well as a NodeId, a span, etc).
///
/// More specifically, it is one of either:
///
///   - A function item,
///   - A closure expr (i.e., an ExprKind::Closure), or
///   - The default implementation for a trait method.
///
/// To construct one, use the `Code::from_node` function.
#[derive(Copy, Clone, Debug)]
pub struct FnLikeNode<'a> {
    node: Node<'a>,
}

/// MaybeFnLike wraps a method that indicates if an object
/// corresponds to some FnLikeNode.
trait MaybeFnLike {
    fn is_fn_like(&self) -> bool;
}

impl MaybeFnLike for hir::Item<'_> {
    fn is_fn_like(&self) -> bool {
        matches!(self.kind, hir::ItemKind::Fn(..))
    }
}

impl MaybeFnLike for hir::ImplItem<'_> {
    fn is_fn_like(&self) -> bool {
        matches!(self.kind, hir::ImplItemKind::Fn(..))
    }
}

impl MaybeFnLike for hir::TraitItem<'_> {
    fn is_fn_like(&self) -> bool {
        matches!(self.kind, hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)))
    }
}

impl MaybeFnLike for hir::Expr<'_> {
    fn is_fn_like(&self) -> bool {
        matches!(self.kind, hir::ExprKind::Closure(..))
    }
}

/// Carries either an FnLikeNode or an Expr, as these are the two
/// constructs that correspond to "code" (as in, something from which
/// we can construct a control-flow graph).
#[derive(Copy, Clone)]
pub enum Code<'a> {
    FnLike(FnLikeNode<'a>),
    Expr(&'a Expr<'a>),
}

impl<'a> Code<'a> {
    pub fn id(&self) -> hir::HirId {
        match *self {
            Code::FnLike(node) => node.id(),
            Code::Expr(block) => block.hir_id,
        }
    }

    /// Attempts to construct a Code from presumed FnLike or Expr node input.
    pub fn from_node(map: &Map<'a>, id: hir::HirId) -> Option<Code<'a>> {
        match map.get(id) {
            Node::Block(_) => {
                //  Use the parent, hopefully an expression node.
                Code::from_node(map, map.get_parent_node(id))
            }
            Node::Expr(expr) => Some(Code::Expr(expr)),
            node => FnLikeNode::from_node(node).map(Code::FnLike),
        }
    }
}

/// These are all the components one can extract from a fn item for
/// use when implementing FnLikeNode operations.
struct ItemFnParts<'a> {
    ident: Ident,
    decl: &'a hir::FnDecl<'a>,
    header: hir::FnHeader,
    vis: &'a hir::Visibility<'a>,
    generics: &'a hir::Generics<'a>,
    body: hir::BodyId,
    id: hir::HirId,
    span: Span,
}

/// These are all the components one can extract from a closure expr
/// for use when implementing FnLikeNode operations.
struct ClosureParts<'a> {
    decl: &'a FnDecl<'a>,
    body: hir::BodyId,
    id: hir::HirId,
    span: Span,
}

impl<'a> ClosureParts<'a> {
    fn new(d: &'a FnDecl<'a>, b: hir::BodyId, id: hir::HirId, s: Span) -> Self {
        ClosureParts { decl: d, body: b, id, span: s }
    }
}

impl<'a> FnLikeNode<'a> {
    /// Attempts to construct a FnLikeNode from presumed FnLike node input.
    pub fn from_node(node: Node<'_>) -> Option<FnLikeNode<'_>> {
        let fn_like = match node {
            Node::Item(item) => item.is_fn_like(),
            Node::TraitItem(tm) => tm.is_fn_like(),
            Node::ImplItem(it) => it.is_fn_like(),
            Node::Expr(e) => e.is_fn_like(),
            _ => false,
        };
        fn_like.then_some(FnLikeNode { node })
    }

    pub fn body(self) -> hir::BodyId {
        self.handle(
            |i: ItemFnParts<'a>| i.body,
            |_, _, _: &'a hir::FnSig<'a>, _, body: hir::BodyId, _| body,
            |c: ClosureParts<'a>| c.body,
        )
    }

    pub fn decl(self) -> &'a FnDecl<'a> {
        self.handle(
            |i: ItemFnParts<'a>| &*i.decl,
            |_, _, sig: &'a hir::FnSig<'a>, _, _, _| &sig.decl,
            |c: ClosureParts<'a>| c.decl,
        )
    }

    pub fn span(self) -> Span {
        self.handle(
            |i: ItemFnParts<'_>| i.span,
            |_, _, _: &'a hir::FnSig<'a>, _, _, span| span,
            |c: ClosureParts<'_>| c.span,
        )
    }

    pub fn id(self) -> hir::HirId {
        self.handle(
            |i: ItemFnParts<'_>| i.id,
            |id, _, _: &'a hir::FnSig<'a>, _, _, _| id,
            |c: ClosureParts<'_>| c.id,
        )
    }

    pub fn constness(self) -> hir::Constness {
        self.kind().header().map_or(hir::Constness::NotConst, |header| header.constness)
    }

    pub fn asyncness(self) -> hir::IsAsync {
        self.kind().header().map_or(hir::IsAsync::NotAsync, |header| header.asyncness)
    }

    pub fn unsafety(self) -> hir::Unsafety {
        self.kind().header().map_or(hir::Unsafety::Normal, |header| header.unsafety)
    }

    pub fn kind(self) -> FnKind<'a> {
        let item = |p: ItemFnParts<'a>| -> FnKind<'a> {
            FnKind::ItemFn(p.ident, p.generics, p.header, p.vis)
        };
        let closure = |_: ClosureParts<'a>| FnKind::Closure;
        let method =
            |_, ident: Ident, sig: &'a hir::FnSig<'a>, vis, _, _| FnKind::Method(ident, sig, vis);
        self.handle(item, method, closure)
    }

    fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A
    where
        I: FnOnce(ItemFnParts<'a>) -> A,
        M: FnOnce(
            hir::HirId,
            Ident,
            &'a hir::FnSig<'a>,
            Option<&'a hir::Visibility<'a>>,
            hir::BodyId,
            Span,
        ) -> A,
        C: FnOnce(ClosureParts<'a>) -> A,
    {
        match self.node {
            Node::Item(i) => match i.kind {
                hir::ItemKind::Fn(ref sig, ref generics, block) => item_fn(ItemFnParts {
                    id: i.hir_id(),
                    ident: i.ident,
                    decl: &sig.decl,
                    body: block,
                    vis: &i.vis,
                    span: i.span,
                    header: sig.header,
                    generics,
                }),
                _ => bug!("item FnLikeNode that is not fn-like"),
            },
            Node::TraitItem(ti) => match ti.kind {
                hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
                    method(ti.hir_id(), ti.ident, sig, None, body, ti.span)
                }
                _ => bug!("trait method FnLikeNode that is not fn-like"),
            },
            Node::ImplItem(ii) => match ii.kind {
                hir::ImplItemKind::Fn(ref sig, body) => {
                    method(ii.hir_id(), ii.ident, sig, Some(&ii.vis), body, ii.span)
                }
                _ => bug!("impl method FnLikeNode that is not fn-like"),
            },
            Node::Expr(e) => match e.kind {
                hir::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) => {
                    closure(ClosureParts::new(&decl, block, e.hir_id, e.span))
                }
                _ => bug!("expr FnLikeNode that is not fn-like"),
            },
            _ => bug!("other FnLikeNode that is not fn-like"),
        }
    }
}
<commit_msg>Cleanup dead code in hir::map::blocks.<commit_after>//! This module provides a simplified abstraction for working with
//! code blocks identified by their integer `NodeId`. In particular,
//! it captures a common set of attributes that all "function-like
//! things" (represented by `FnLike` instances) share. For example,
//! all `FnLike` instances have a type signature (be it explicit or
//! inferred). And all `FnLike` instances have a body, i.e., the code
//! that is run when the function-like thing it represents is invoked.
//!
//! With the above abstraction in place, one can treat the program
//! text as a collection of blocks of code (and most such blocks are
//! nested within a uniquely determined `FnLike`), and users can ask
//! for the `Code` associated with a particular NodeId.

use rustc_hir as hir;
use rustc_hir::intravisit::FnKind;
use rustc_hir::Node;

/// An FnLikeNode is a Node that is like a fn, in that it has a decl
/// and a body (as well as a NodeId, a span, etc).
///
/// More specifically, it is one of either:
///
///   - A function item,
///   - A closure expr (i.e., an ExprKind::Closure), or
///   - The default implementation for a trait method.
///
/// To construct one, use the `Code::from_node` function.
#[derive(Copy, Clone, Debug)]
pub struct FnLikeNode<'a> {
    node: Node<'a>,
}

impl<'a> FnLikeNode<'a> {
    /// Attempts to construct a FnLikeNode from presumed FnLike node input.
    pub fn from_node(node: Node<'_>) -> Option<FnLikeNode<'_>> {
        let fn_like = match node {
            Node::Item(item) => matches!(item.kind, hir::ItemKind::Fn(..)),
            Node::TraitItem(tm) => {
                matches!(tm.kind, hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)))
            }
            Node::ImplItem(it) => matches!(it.kind, hir::ImplItemKind::Fn(..)),
            Node::Expr(e) => matches!(e.kind, hir::ExprKind::Closure(..)),
            _ => false,
        };
        fn_like.then_some(FnLikeNode { node })
    }

    pub fn constness(self) -> hir::Constness {
        self.kind().header().map_or(hir::Constness::NotConst, |header| header.constness)
    }

    pub fn asyncness(self) -> hir::IsAsync {
        self.kind().header().map_or(hir::IsAsync::NotAsync, |header| header.asyncness)
    }

    pub fn kind(self) -> FnKind<'a> {
        match self.node {
            Node::Item(i) => match i.kind {
                hir::ItemKind::Fn(ref sig, ref generics, _) => {
                    FnKind::ItemFn(i.ident, generics, sig.header, &i.vis)
                }
                _ => bug!("item FnLikeNode that is not fn-like"),
            },
            Node::TraitItem(ti) => match ti.kind {
                hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(_)) => {
                    FnKind::Method(ti.ident, sig, None)
                }
                _ => bug!("trait method FnLikeNode that is not fn-like"),
            },
            Node::ImplItem(ii) => match ii.kind {
                hir::ImplItemKind::Fn(ref sig, _) => FnKind::Method(ii.ident, sig, Some(&ii.vis)),
                _ => bug!("impl method FnLikeNode that is not fn-like"),
            },
            Node::Expr(e) => match e.kind {
                hir::ExprKind::Closure(..) => FnKind::Closure,
                _ => bug!("expr FnLikeNode that is not fn-like"),
            },
            _ => bug!("other FnLikeNode that is not fn-like"),
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::env::{current_dir, vars};
use std::io::{self, Write};

use anyhow::{bail, Context, Result};
use log::error;

use pueue::message::*;
use pueue::platform::socket::*;
use pueue::protocol::*;
use pueue::settings::Settings;

use crate::cli::{Opt, SubCommand};
use crate::commands::edit::*;
use crate::commands::local_follow::*;
use crate::commands::restart::*;
use crate::output::*;

/// This struct contains the base logic for the client.
/// The client is responsible for connecting to the daemon, sending instructions
/// and interpreting their responses.
///
/// Most commands are a simple ping-pong. However, some commands require a more complex
/// communication pattern, such as the `follow` command, which continuously streams the output of a task.
pub struct Client {
    opt: Opt,
    settings: Settings,
    socket: Socket,
}

impl Client {
    /// Connect to the daemon, authorize via secret and return a new initialized Client.
    pub async fn new(settings: Settings, opt: Opt) -> Result<Self> {
        // // Commandline argument overwrites the configuration files values for address
        // let address = if let Some(address) = opt.address.clone() {
        //     address
        // } else {
        //     settings.client.daemon_address
        // };

        // Commandline argument overwrites the configuration files values for port
        let (unix_socket_path, port) = {
            // Return the unix socket path, if we're supposed to use it.
            if settings.shared.use_unix_socket {
                (Some(settings.shared.unix_socket_path.clone()), None)
            } else {
                // Otherwise use tcp sockets and a given port
                // Commandline argument overwrites the configuration files values for port.
                let port = if let Some(port) = opt.port.clone() {
                    port
                } else {
                    settings.shared.port.clone()
                };

                (None, Some(port))
            }
        };

        let mut socket = get_client(unix_socket_path, port).await?;

        // Send the secret to the daemon
        let secret = settings.shared.secret.clone().into_bytes();
        send_bytes(secret, &mut socket).await?;

        Ok(Client {
            opt,
            settings,
            socket,
        })
    }

    /// This is the function where the actual communication and logic starts.
    /// At this point everything is initialized, the connection is up and
    /// we can finally start doing stuff.
    ///
    /// The command handling is splitted into "simple" and "complex" commands.
    pub async fn start(&mut self) -> Result<()> {
        // Return early, if the command has already been handled.
        if self.handle_complex_command().await? {
            return Ok(());
        }

        // The handling of "generic" commands is encapsulated in this function.
        self.handle_simple_command().await?;

        Ok(())
    }

    /// Handle all complex client-side functionalities.
    /// Complex functionalities need some special handling and are contained
    /// in their own functions with their own communication code.
    /// Such functionalities includes reading local files, data streaming
    /// and sending multiple messages.
    ///
    /// Returns `true`, if the current command has been handled by this function.
    /// This indicates that the client can now shut down.
    async fn handle_complex_command(&mut self) -> Result<bool> {
        // This match handles all "complex" commands.
        match &self.opt.cmd {
            SubCommand::Edit { task_id, path } => {
                let message = edit(&mut self.socket, *task_id, *path).await?;
                self.handle_response(message);
                Ok(true)
            }
            SubCommand::Restart {
                task_ids,
                start_immediately,
                stashed,
                edit,
                path,
            } => {
                restart(
                    &mut self.socket,
                    task_ids.clone(),
                    *start_immediately,
                    *stashed,
                    *edit,
                    *path,
                )
                .await?;
                Ok(true)
            }
            SubCommand::Follow { task_id, err } => {
                // Simple log output follows for local logs don't need any communication with the daemon.
                // Thereby we handle this separately over here.
                if self.settings.client.read_local_logs {
                    local_follow(
                        &mut self.socket,
                        self.settings.shared.pueue_directory.clone(),
                        task_id,
                        *err,
                    )
                    .await?;
                    return Ok(true);
                }
                Ok(false)
            }
            _ => Ok(false),
        }
    }

    /// Handle logic that's super generic on the client-side.
    /// This always follows a singular ping-pong pattern.
    /// One message to the daemon, one response, Done.
    async fn handle_simple_command(&mut self) -> Result<()> {
        // Create the message that should be sent to the daemon
        // depending on the given commandline options.
        let message = self.get_message_from_opt()?;

        // Create the message payload and send it to the daemon.
        send_message(message, &mut self.socket).await?;

        // Check if we can receive the response from the daemon
        let mut response = receive_message(&mut self.socket).await?;

        // Check if we can receive the response from the daemon
        while self.handle_response(response) {
            response = receive_message(&mut self.socket).await?;
        }

        Ok(())
    }

    /// Most returned messages can be handled in a generic fashion.
    /// However, some commands require continuous receiving of messages (streaming).
    ///
    /// If this function returns `Ok(true)`, the parent function will continue to receive
    /// and handle messages from the daemon. Otherwise the client will simply exit.
    fn handle_response(&self, message: Message) -> bool {
        match message {
            Message::Success(text) => print_success(&text),
            Message::Failure(text) => print_error(&text),
            Message::StatusResponse(state) => print_state(state, &self.opt.cmd),
            Message::LogResponse(task_logs) => print_logs(task_logs, &self.opt.cmd, &self.settings),
            Message::Stream(text) => {
                print!("{}", text);
                io::stdout().flush().unwrap();
                return true;
            }
            _ => error!("Received unhandled response message"),
        };

        false
    }

    /// Prints a warning and prompt for given action and tasks.
    /// Returns `Ok(())` if the action was confirmed.
    fn handle_user_confirmation(&self, action: &str, task_ids: &[usize]) -> Result<()> {
        // printing warning and prompt
        println!(
            "You are trying to {}: {}",
            action,
            task_ids
                .iter()
                .map(|t| format!("task{}", t.to_string()))
                .collect::<Vec<String>>()
                .join(", ")
        );

        let mut input = String::new();

        loop {
            print!("Do you want to continue [Y/n]: ");
            io::stdout().flush().unwrap();
            input.clear();
            io::stdin().read_line(&mut input)?;

            match input.chars().next().unwrap_or("y") {
                'N' | 'n' => {
                    println!("Aborted!");
                    std::process::exit(1);
                },
                '\n' | 'Y' | 'y' => {
                    return Ok(());
                },
                _ => { continue; }
            }
        }
    }

    /// Convert the cli command into the message that's being sent to the server,
    /// so it can be understood by the daemon.
    fn get_message_from_opt(&self) -> Result<Message> {
        match &self.opt.cmd {
            SubCommand::Add {
                command,
                start_immediately,
                stashed,
                group,
                delay_until,
                dependencies,
            } => {
                let cwd_pathbuf = current_dir()?;
                let cwd = cwd_pathbuf
                    .to_str()
                    .context("Cannot parse current working directory (Invalid utf8?)")?;

                let mut envs = HashMap::new();
                // Save all environment variables for later injection into the started task
                for (key, value) in vars() {
                    envs.insert(key, value);
                }

                Ok(Message::Add(AddMessage {
                    command: command.join(" "),
                    path: cwd.to_string(),
                    envs,
                    start_immediately: *start_immediately,
                    stashed: *stashed,
                    group: group.clone(),
                    enqueue_at: *delay_until,
                    dependencies: dependencies.to_vec(),
                    ignore_aliases: false,
                }))
            }
            SubCommand::Remove { task_ids } => {
                if self.settings.client.print_remove_warnings {
                    self.handle_user_confirmation("remove", task_ids);
                }
                Ok(Message::Remove(task_ids.clone()))
            }
            SubCommand::Stash { task_ids } => Ok(Message::Stash(task_ids.clone())),
            SubCommand::Switch {
                task_id_1,
                task_id_2,
            } => {
                let message = SwitchMessage {
                    task_id_1: *task_id_1,
                    task_id_2: *task_id_2,
                };
                Ok(Message::Switch(message))
            }
            SubCommand::Enqueue {
                task_ids,
                delay_until,
            } => {
                let message = EnqueueMessage {
                    task_ids: task_ids.clone(),
                    enqueue_at: *delay_until,
                };
                Ok(Message::Enqueue(message))
            }
            SubCommand::Start {
                task_ids,
                group,
                all,
                children,
            } => {
                let message = StartMessage {
                    task_ids: task_ids.clone(),
                    group: group.clone(),
                    all: *all,
                    children: *children,
                };
                Ok(Message::Start(message))
            }
            SubCommand::Pause {
                task_ids,
                group,
                wait,
                all,
                children,
            } => {
                let message = PauseMessage {
                    task_ids: task_ids.clone(),
                    group: group.clone(),
                    wait: *wait,
                    all: *all,
                    children: *children,
                };
                Ok(Message::Pause(message))
            }
            SubCommand::Kill {
                task_ids,
                group,
                default,
                all,
                children,
            } => {
                if self.settings.client.print_remove_warnings {
                    self.handle_user_confirmation("kill", task_ids);
                }
                let message = KillMessage {
                    task_ids: task_ids.clone(),
                    group: group.clone(),
                    default: *default,
                    all: *all,
                    children: *children,
                };
                Ok(Message::Kill(message))
            }
            SubCommand::Send { task_id, input } => {
                let message = SendMessage {
                    task_id: *task_id,
                    input: input.clone(),
                };
                Ok(Message::Send(message))
            }
            SubCommand::Group { add, remove } => {
                let message = GroupMessage {
                    add: add.clone(),
                    remove: remove.clone(),
                };
                Ok(Message::Group(message))
            }
            SubCommand::Status { .. } => Ok(Message::Status),
            SubCommand::Log { task_ids, .. } => {
                let message = LogRequestMessage {
                    task_ids: task_ids.clone(),
                    send_logs: !self.settings.client.read_local_logs,
                };
                Ok(Message::Log(message))
            }
            SubCommand::Follow { task_id, err } => {
                let message = StreamRequestMessage {
                    task_id: *task_id,
                    err: *err,
                };
                Ok(Message::StreamRequest(message))
            }
            SubCommand::Clean => Ok(Message::Clean),
            SubCommand::Reset { children } => Ok(Message::Reset(*children)),
            SubCommand::Shutdown => Ok(Message::DaemonShutdown),
            SubCommand::Parallel {
                parallel_tasks,
                group,
            } => {
                let message = ParallelMessage {
                    parallel_tasks: *parallel_tasks,
                    group: group.clone(),
                };
                Ok(Message::Parallel(message))
            }
            SubCommand::Completions { .. } => bail!("Completions have to be handled earlier"),
            SubCommand::Restart { .. } => bail!("Restarts have to be handled earlier"),
            SubCommand::Edit { .. } => bail!("Edits have to be handled earlier"),
        }
    }
}
<commit_msg>Fix not using Result<commit_after>use std::collections::HashMap;
use std::env::{current_dir, vars};
use std::io::{self, Write};

use anyhow::{bail, Context, Result};
use log::error;

use pueue::message::*;
use pueue::platform::socket::*;
use pueue::protocol::*;
use pueue::settings::Settings;

use crate::cli::{Opt, SubCommand};
use crate::commands::edit::*;
use crate::commands::local_follow::*;
use crate::commands::restart::*;
use crate::output::*;

/// This struct contains the base logic for the client.
/// The client is responsible for connecting to the daemon, sending instructions
/// and interpreting their responses.
///
/// Most commands are a simple ping-pong. However, some commands require a more complex
/// communication pattern, such as the `follow` command, which continuously streams the output of a task.
pub struct Client {
    opt: Opt,
    settings: Settings,
    socket: Socket,
}

impl Client {
    /// Connect to the daemon, authorize via secret and return a new initialized Client.
    pub async fn new(settings: Settings, opt: Opt) -> Result<Self> {
        // // Commandline argument overwrites the configuration files values for address
        // let address = if let Some(address) = opt.address.clone() {
        //     address
        // } else {
        //     settings.client.daemon_address
        // };

        // Commandline argument overwrites the configuration files values for port
        let (unix_socket_path, port) = {
            // Return the unix socket path, if we're supposed to use it.
            if settings.shared.use_unix_socket {
                (Some(settings.shared.unix_socket_path.clone()), None)
            } else {
                // Otherwise use tcp sockets and a given port
                // Commandline argument overwrites the configuration files values for port.
                let port = if let Some(port) = opt.port.clone() {
                    port
                } else {
                    settings.shared.port.clone()
                };

                (None, Some(port))
            }
        };

        let mut socket = get_client(unix_socket_path, port).await?;

        // Send the secret to the daemon
        let secret = settings.shared.secret.clone().into_bytes();
        send_bytes(secret, &mut socket).await?;

        Ok(Client {
            opt,
            settings,
            socket,
        })
    }

    /// This is the function where the actual communication and logic starts.
    /// At this point everything is initialized, the connection is up and
    /// we can finally start doing stuff.
    ///
    /// The command handling is splitted into "simple" and "complex" commands.
    pub async fn start(&mut self) -> Result<()> {
        // Return early, if the command has already been handled.
        if self.handle_complex_command().await? {
            return Ok(());
        }

        // The handling of "generic" commands is encapsulated in this function.
        self.handle_simple_command().await?;

        Ok(())
    }

    /// Handle all complex client-side functionalities.
    /// Complex functionalities need some special handling and are contained
    /// in their own functions with their own communication code.
    /// Such functionalities includes reading local files, data streaming
    /// and sending multiple messages.
    ///
    /// Returns `true`, if the current command has been handled by this function.
    /// This indicates that the client can now shut down.
    async fn handle_complex_command(&mut self) -> Result<bool> {
        // This match handles all "complex" commands.
        match &self.opt.cmd {
            SubCommand::Edit { task_id, path } => {
                let message = edit(&mut self.socket, *task_id, *path).await?;
                self.handle_response(message);
                Ok(true)
            }
            SubCommand::Restart {
                task_ids,
                start_immediately,
                stashed,
                edit,
                path,
            } => {
                restart(
                    &mut self.socket,
                    task_ids.clone(),
                    *start_immediately,
                    *stashed,
                    *edit,
                    *path,
                )
                .await?;
                Ok(true)
            }
            SubCommand::Follow { task_id, err } => {
                // Simple log output follows for local logs don't need any communication with the daemon.
                // Thereby we handle this separately over here.
                if self.settings.client.read_local_logs {
                    local_follow(
                        &mut self.socket,
                        self.settings.shared.pueue_directory.clone(),
                        task_id,
                        *err,
                    )
                    .await?;
                    return Ok(true);
                }
                Ok(false)
            }
            _ => Ok(false),
        }
    }

    /// Handle logic that's super generic on the client-side.
    /// This always follows a singular ping-pong pattern.
    /// One message to the daemon, one response, Done.
    async fn handle_simple_command(&mut self) -> Result<()> {
        // Create the message that should be sent to the daemon
        // depending on the given commandline options.
        let message = self.get_message_from_opt()?;

        // Create the message payload and send it to the daemon.
        send_message(message, &mut self.socket).await?;

        // Check if we can receive the response from the daemon
        let mut response = receive_message(&mut self.socket).await?;

        // Check if we can receive the response from the daemon
        while self.handle_response(response) {
            response = receive_message(&mut self.socket).await?;
        }

        Ok(())
    }

    /// Most returned messages can be handled in a generic fashion.
    /// However, some commands require continuous receiving of messages (streaming).
    ///
    /// If this function returns `Ok(true)`, the parent function will continue to receive
    /// and handle messages from the daemon. Otherwise the client will simply exit.
    fn handle_response(&self, message: Message) -> bool {
        match message {
            Message::Success(text) => print_success(&text),
            Message::Failure(text) => print_error(&text),
            Message::StatusResponse(state) => print_state(state, &self.opt.cmd),
            Message::LogResponse(task_logs) => print_logs(task_logs, &self.opt.cmd, &self.settings),
            Message::Stream(text) => {
                print!("{}", text);
                io::stdout().flush().unwrap();
                return true;
            }
            _ => error!("Received unhandled response message"),
        };

        false
    }

    /// Prints a warning and prompt for given action and tasks.
    /// Returns `Ok(())` if the action was confirmed.
    fn handle_user_confirmation(&self, action: &str, task_ids: &[usize]) -> Result<()> {
        // printing warning and prompt
        println!(
            "You are trying to {}: {}",
            action,
            task_ids
                .iter()
                .map(|t| format!("task{}", t.to_string()))
                .collect::<Vec<String>>()
                .join(", ")
        );

        let mut input = String::new();

        loop {
            print!("Do you want to continue [Y/n]: ");
            io::stdout().flush().unwrap();
            input.clear();
            io::stdin().read_line(&mut input)?;

            match input.chars().next().unwrap() {
                'N' | 'n' => {
                    println!("Aborted!");
                    std::process::exit(1);
                }
                '\n' | 'Y' | 'y' => {
                    break;
                }
                _ => {
                    continue;
                }
            }
        }

        Ok(())
    }

    /// Convert the cli command into the message that's being sent to the server,
    /// so it can be understood by the daemon.
    fn get_message_from_opt(&self) -> Result<Message> {
        match &self.opt.cmd {
            SubCommand::Add {
                command,
                start_immediately,
                stashed,
                group,
                delay_until,
                dependencies,
            } => {
                let cwd_pathbuf = current_dir()?;
                let cwd = cwd_pathbuf
                    .to_str()
                    .context("Cannot parse current working directory (Invalid utf8?)")?;

                let mut envs = HashMap::new();
                // Save all environment variables for later injection into the started task
                for (key, value) in vars() {
                    envs.insert(key, value);
                }

                Ok(Message::Add(AddMessage {
                    command: command.join(" "),
                    path: cwd.to_string(),
                    envs,
                    start_immediately: *start_immediately,
                    stashed: *stashed,
                    group: group.clone(),
                    enqueue_at: *delay_until,
                    dependencies: dependencies.to_vec(),
                    ignore_aliases: false,
                }))
            }
            SubCommand::Remove { task_ids } => {
                if self.settings.client.print_remove_warnings {
                    self.handle_user_confirmation("remove", task_ids)?;
                }
                Ok(Message::Remove(task_ids.clone()))
            }
            SubCommand::Stash { task_ids } => Ok(Message::Stash(task_ids.clone())),
            SubCommand::Switch {
                task_id_1,
                task_id_2,
            } => {
                let message = SwitchMessage {
                    task_id_1: *task_id_1,
                    task_id_2: *task_id_2,
                };
                Ok(Message::Switch(message))
            }
            SubCommand::Enqueue {
                task_ids,
                delay_until,
            } => {
                let message = EnqueueMessage {
                    task_ids: task_ids.clone(),
                    enqueue_at: *delay_until,
                };
                Ok(Message::Enqueue(message))
            }
            SubCommand::Start {
                task_ids,
                group,
                all,
                children,
            } => {
                let message = StartMessage {
                    task_ids: task_ids.clone(),
                    group: group.clone(),
                    all: *all,
                    children: *children,
                };
                Ok(Message::Start(message))
            }
            SubCommand::Pause {
                task_ids,
                group,
                wait,
                all,
                children,
            } => {
                let message = PauseMessage {
                    task_ids: task_ids.clone(),
                    group: group.clone(),
                    wait: *wait,
                    all: *all,
                    children: *children,
                };
                Ok(Message::Pause(message))
            }
            SubCommand::Kill {
                task_ids,
                group,
                default,
                all,
                children,
            } => {
                if self.settings.client.print_remove_warnings {
                    self.handle_user_confirmation("kill", task_ids)?;
                }
                let message = KillMessage {
                    task_ids: task_ids.clone(),
                    group: group.clone(),
                    default: *default,
                    all: *all,
                    children: *children,
                };
                Ok(Message::Kill(message))
            }
            SubCommand::Send { task_id, input } => {
                let message = SendMessage {
                    task_id: *task_id,
                    input: input.clone(),
                };
                Ok(Message::Send(message))
            }
            SubCommand::Group { add, remove } => {
                let message = GroupMessage {
                    add: add.clone(),
                    remove: remove.clone(),
                };
                Ok(Message::Group(message))
            }
            SubCommand::Status { .. } => Ok(Message::Status),
            SubCommand::Log { task_ids, .. } => {
                let message = LogRequestMessage {
                    task_ids: task_ids.clone(),
                    send_logs: !self.settings.client.read_local_logs,
                };
                Ok(Message::Log(message))
            }
            SubCommand::Follow { task_id, err } => {
                let message = StreamRequestMessage {
                    task_id: *task_id,
                    err: *err,
                };
                Ok(Message::StreamRequest(message))
            }
            SubCommand::Clean => Ok(Message::Clean),
            SubCommand::Reset { children } => Ok(Message::Reset(*children)),
            SubCommand::Shutdown => Ok(Message::DaemonShutdown),
            SubCommand::Parallel {
                parallel_tasks,
                group,
            } => {
                let message = ParallelMessage {
                    parallel_tasks: *parallel_tasks,
                    group: group.clone(),
                };
                Ok(Message::Parallel(message))
            }
            SubCommand::Completions { .. } => bail!("Completions have to be handled earlier"),
            SubCommand::Restart { .. } => bail!("Restarts have to be handled earlier"),
            SubCommand::Edit { .. } => bail!("Edits have to be handled earlier"),
        }
    }
}
<|endoftext|>


<commit_before>use super::{Observation, Transition, Domain, runge_kutta4};

use std::f64::consts::PI;
use consts::{G, PI_OVER_2};
use ndarray::{arr1, Array1, NdIndex, Ix1};
use geometry::{ActionSpace, RegularSpace};
use geometry::dimensions::{Continuous, Discrete};

// Link masses:
const M1: f64 = 1.0;
const M2: f64 = 1.0;

// Link lengths:
const L1: f64 = 1.0;
const L2: f64 = 1.0;

// Link centre of masses:
const LC1: f64 = 0.5;
const LC2: f64 = 0.5;

// Link moment of intertias:
const I1: f64 = 1.0;
const I2: f64 = 1.0;

const DT: f64 = 0.2;

const LIMITS_THETA1: (f64, f64) = (-PI, PI);
const LIMITS_THETA2: (f64, f64) = (-PI, PI);
const LIMITS_DTHETA1: (f64, f64) = (-4.0*PI, 4.0*PI);
const LIMITS_DTHETA2: (f64, f64) = (-9.0*PI, 9.0*PI);

const REWARD_STEP: f64 = -1.0;
const REWARD_TERMINAL: f64 = 0.0;

const TORQUE: f64 = 1.0;
const ALL_ACTIONS: [f64; 3] = [-TORQUE, 0.0, TORQUE];

#[derive(Debug, Clone, Copy)]
enum StateIndex {
    THETA1 = 0,
    THETA2 = 1,
    DTHETA1 = 2,
    DTHETA2 = 3,
}

unsafe impl NdIndex<Ix1> for StateIndex {
    #[inline]
    fn index_checked(&self, dim: &Ix1, strides: &Ix1) -> Option<isize> {
        (*self as usize).index_checked(dim, strides)
    }

    #[inline(always)]
    fn index_unchecked(&self, strides: &Ix1) -> isize {
        (*self as usize).index_unchecked(strides)
    }
}

/// Classic double pendulum control domain.
///
/// The acrobot is a 2-link pendulum environment in which only the second joint actuated. The goal
/// is to swing the end-effector to a distance equal to the length of one link above the base.
pub struct Acrobat {
    state: Array1<f64>,
}

impl Acrobat {
    fn new(theta1: f64, theta2: f64, dtheta1: f64, dtheta2: f64) -> Acrobat {
        Acrobat {
            state: arr1(&vec![theta1, theta2, dtheta1, dtheta2])
        }
    }

    fn update_state(&mut self, a: usize) {
        let fx = |_x, y| Acrobat::grad(ALL_ACTIONS[a], y);
        let mut ns = runge_kutta4(&fx, 0.0, self.state.clone(), DT);

        ns[StateIndex::THETA1] = wrap!(LIMITS_THETA1.0, ns[StateIndex::THETA1], LIMITS_THETA1.1);
        ns[StateIndex::THETA2] = wrap!(LIMITS_THETA2.0, ns[StateIndex::THETA2], LIMITS_THETA2.1);

        ns[StateIndex::DTHETA1] =
            clip!(LIMITS_DTHETA1.0, ns[StateIndex::DTHETA1], LIMITS_DTHETA1.1);
        ns[StateIndex::DTHETA2] =
            clip!(LIMITS_DTHETA2.0, ns[StateIndex::DTHETA2], LIMITS_DTHETA2.1);

        self.state = ns;
    }

    fn grad(torque: f64, state: Array1<f64>) -> Array1<f64> {
        let theta1 = state[StateIndex::THETA1];
        let theta2 = state[StateIndex::THETA2];
        let dtheta1 = state[StateIndex::DTHETA1];
        let dtheta2 = state[StateIndex::DTHETA2];

        let sin_t2 = theta1.sin();
        let cos_t2 = theta2.cos();

        let d1 =
            M1*LC1*LC1 + M2*(L1*L1 + LC2*LC2 + 2.0*L1*LC2*cos_t2) + I1 + I2;
        let d2 = M2*(LC2*LC2 + L1*LC2*cos_t2) + I2;

        let phi2 = M2*LC2*G*(theta1 + theta2 - PI_OVER_2).cos();
        let phi1 =
            -1.0*L1*LC2*dtheta2*dtheta2*sin_t2 -
            2.0*M2*L1*LC2*dtheta2*dtheta1*sin_t2 +
            (M1*LC1 + M2*L1)*G*(theta1 - PI_OVER_2).cos() + phi2;

        let ddtheta2 =
            (torque + d2/d1*phi1 - M2*L1*LC2*dtheta1*dtheta1*sin_t2 - phi2) /
            (M2*LC2*LC2 + I2 - d2*d2/d1);
        let ddtheta1 = -(d2*ddtheta2 + phi1) / d1;

        arr1(&vec![dtheta1, dtheta2, ddtheta1, ddtheta2])
    }
}

impl Default for Acrobat {
    fn default() -> Acrobat {
        Acrobat::new(0.0, 0.0, 0.0, 0.0)
    }
}

impl Domain for Acrobat {
    type StateSpace = RegularSpace<Continuous>;
    type ActionSpace = ActionSpace;

    fn emit(&self) -> Observation<Self::StateSpace, Self::ActionSpace> {
        if self.is_terminal() {
            Observation::Terminal(self.state.to_vec())
        } else {
            Observation::Full {
                state: self.state.to_vec(),
                actions: vec![0, 1, 2],
            }
        }
    }

    fn step(&mut self, a: usize) -> Transition<Self::StateSpace, Self::ActionSpace> {
        let from = self.emit();

        self.update_state(a);
        let to = self.emit();
        let r = self.reward(&from, &to);

        Transition {
            from: from,
            action: a,
            reward: r,
            to: to,
        }
    }

    fn is_terminal(&self) -> bool {
        let theta1 = self.state[StateIndex::THETA1];
        let theta2 = self.state[StateIndex::THETA2];

        theta1.cos() + (theta1 + theta2).cos() < -1.0
    }

    fn reward(&self,
              _: &Observation<Self::StateSpace, Self::ActionSpace>,
              to: &Observation<Self::StateSpace, Self::ActionSpace>) -> f64
    {
        match to {
            &Observation::Terminal(_) => REWARD_TERMINAL,
            _ => REWARD_STEP,
        }
    }

    fn state_space(&self) -> Self::StateSpace {
        Self::StateSpace::new()
            .push(Continuous::new(LIMITS_THETA1.0, LIMITS_THETA1.1))
            .push(Continuous::new(LIMITS_THETA2.0, LIMITS_THETA2.1))
            .push(Continuous::new(LIMITS_DTHETA1.0, LIMITS_DTHETA1.1))
            .push(Continuous::new(LIMITS_DTHETA2.0, LIMITS_DTHETA2.1))
    }

    fn action_space(&self) -> ActionSpace {
        ActionSpace::new(Discrete::new(3))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use domains::{Observation, Domain};

    #[test]
    fn test_initial_observation() {
        let m = Acrobat::default();

        match m.emit() {
            Observation::Full { ref state, .. } => {
                assert_eq!(state[0], 0.0);
                assert_eq!(state[1], 0.0);
                assert_eq!(state[2], 0.0);
                assert_eq!(state[3], 0.0);
            }
            _ => panic!("Should yield a fully observable state."),
        }
    }

    #[test]
    fn test_is_terminal() {
        assert!(!Acrobat::default().is_terminal());
    }
}
<commit_msg>Add note to Acrobat docs<commit_after>use super::{Observation, Transition, Domain, runge_kutta4};

use std::f64::consts::PI;
use consts::{G, PI_OVER_2};
use ndarray::{arr1, Array1, NdIndex, Ix1};
use geometry::{ActionSpace, RegularSpace};
use geometry::dimensions::{Continuous, Discrete};

// Link masses:
const M1: f64 = 1.0;
const M2: f64 = 1.0;

// Link lengths:
const L1: f64 = 1.0;
const L2: f64 = 1.0;

// Link centre of masses:
const LC1: f64 = 0.5;
const LC2: f64 = 0.5;

// Link moment of intertias:
const I1: f64 = 1.0;
const I2: f64 = 1.0;

const DT: f64 = 0.2;

const LIMITS_THETA1: (f64, f64) = (-PI, PI);
const LIMITS_THETA2: (f64, f64) = (-PI, PI);
const LIMITS_DTHETA1: (f64, f64) = (-4.0*PI, 4.0*PI);
const LIMITS_DTHETA2: (f64, f64) = (-9.0*PI, 9.0*PI);

const REWARD_STEP: f64 = -1.0;
const REWARD_TERMINAL: f64 = 0.0;

const TORQUE: f64 = 1.0;
const ALL_ACTIONS: [f64; 3] = [-TORQUE, 0.0, TORQUE];

#[derive(Debug, Clone, Copy)]
enum StateIndex {
    THETA1 = 0,
    THETA2 = 1,
    DTHETA1 = 2,
    DTHETA2 = 3,
}

unsafe impl NdIndex<Ix1> for StateIndex {
    #[inline]
    fn index_checked(&self, dim: &Ix1, strides: &Ix1) -> Option<isize> {
        (*self as usize).index_checked(dim, strides)
    }

    #[inline(always)]
    fn index_unchecked(&self, strides: &Ix1) -> isize {
        (*self as usize).index_unchecked(strides)
    }
}

/// Classic double pendulum control domain.
///
/// The acrobot is a 2-link pendulum environment in which only the second joint actuated. The goal
/// is to swing the end-effector to a distance equal to the length of one link above the base.
///
/// See [https://www.math24.net/double-pendulum/](https://www.math24.net/double-pendulum/)
pub struct Acrobat {
    state: Array1<f64>,
}

impl Acrobat {
    fn new(theta1: f64, theta2: f64, dtheta1: f64, dtheta2: f64) -> Acrobat {
        Acrobat {
            state: arr1(&vec![theta1, theta2, dtheta1, dtheta2])
        }
    }

    fn update_state(&mut self, a: usize) {
        let fx = |_x, y| Acrobat::grad(ALL_ACTIONS[a], y);
        let mut ns = runge_kutta4(&fx, 0.0, self.state.clone(), DT);

        ns[StateIndex::THETA1] = wrap!(LIMITS_THETA1.0, ns[StateIndex::THETA1], LIMITS_THETA1.1);
        ns[StateIndex::THETA2] = wrap!(LIMITS_THETA2.0, ns[StateIndex::THETA2], LIMITS_THETA2.1);

        ns[StateIndex::DTHETA1] =
            clip!(LIMITS_DTHETA1.0, ns[StateIndex::DTHETA1], LIMITS_DTHETA1.1);
        ns[StateIndex::DTHETA2] =
            clip!(LIMITS_DTHETA2.0, ns[StateIndex::DTHETA2], LIMITS_DTHETA2.1);

        self.state = ns;
    }

    fn grad(torque: f64, state: Array1<f64>) -> Array1<f64> {
        let theta1 = state[StateIndex::THETA1];
        let theta2 = state[StateIndex::THETA2];
        let dtheta1 = state[StateIndex::DTHETA1];
        let dtheta2 = state[StateIndex::DTHETA2];

        let sin_t2 = theta1.sin();
        let cos_t2 = theta2.cos();

        let d1 =
            M1*LC1*LC1 + M2*(L1*L1 + LC2*LC2 + 2.0*L1*LC2*cos_t2) + I1 + I2;
        let d2 = M2*(LC2*LC2 + L1*LC2*cos_t2) + I2;

        let phi2 = M2*LC2*G*(theta1 + theta2 - PI_OVER_2).cos();
        let phi1 =
            -1.0*L1*LC2*dtheta2*dtheta2*sin_t2 -
            2.0*M2*L1*LC2*dtheta2*dtheta1*sin_t2 +
            (M1*LC1 + M2*L1)*G*(theta1 - PI_OVER_2).cos() + phi2;

        let ddtheta2 =
            (torque + d2/d1*phi1 - M2*L1*LC2*dtheta1*dtheta1*sin_t2 - phi2) /
            (M2*LC2*LC2 + I2 - d2*d2/d1);
        let ddtheta1 = -(d2*ddtheta2 + phi1) / d1;

        arr1(&vec![dtheta1, dtheta2, ddtheta1, ddtheta2])
    }
}

impl Default for Acrobat {
    fn default() -> Acrobat {
        Acrobat::new(0.0, 0.0, 0.0, 0.0)
    }
}

impl Domain for Acrobat {
    type StateSpace = RegularSpace<Continuous>;
    type ActionSpace = ActionSpace;

    fn emit(&self) -> Observation<Self::StateSpace, Self::ActionSpace> {
        if self.is_terminal() {
            Observation::Terminal(self.state.to_vec())
        } else {
            Observation::Full {
                state: self.state.to_vec(),
                actions: vec![0, 1, 2],
            }
        }
    }

    fn step(&mut self, a: usize) -> Transition<Self::StateSpace, Self::ActionSpace> {
        let from = self.emit();

        self.update_state(a);
        let to = self.emit();
        let r = self.reward(&from, &to);

        Transition {
            from: from,
            action: a,
            reward: r,
            to: to,
        }
    }

    fn is_terminal(&self) -> bool {
        let theta1 = self.state[StateIndex::THETA1];
        let theta2 = self.state[StateIndex::THETA2];

        theta1.cos() + (theta1 + theta2).cos() < -1.0
    }

    fn reward(&self,
              _: &Observation<Self::StateSpace, Self::ActionSpace>,
              to: &Observation<Self::StateSpace, Self::ActionSpace>) -> f64
    {
        match to {
            &Observation::Terminal(_) => REWARD_TERMINAL,
            _ => REWARD_STEP,
        }
    }

    fn state_space(&self) -> Self::StateSpace {
        Self::StateSpace::new()
            .push(Continuous::new(LIMITS_THETA1.0, LIMITS_THETA1.1))
            .push(Continuous::new(LIMITS_THETA2.0, LIMITS_THETA2.1))
            .push(Continuous::new(LIMITS_DTHETA1.0, LIMITS_DTHETA1.1))
            .push(Continuous::new(LIMITS_DTHETA2.0, LIMITS_DTHETA2.1))
    }

    fn action_space(&self) -> ActionSpace {
        ActionSpace::new(Discrete::new(3))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use domains::{Observation, Domain};

    #[test]
    fn test_initial_observation() {
        let m = Acrobat::default();

        match m.emit() {
            Observation::Full { ref state, .. } => {
                assert_eq!(state[0], 0.0);
                assert_eq!(state[1], 0.0);
                assert_eq!(state[2], 0.0);
                assert_eq!(state[3], 0.0);
            }
            _ => panic!("Should yield a fully observable state."),
        }
    }

    #[test]
    fn test_is_terminal() {
        assert!(!Acrobat::default().is_terminal());
    }
}
<|endoftext|>


<commit_before>use std::io;

use super::LogOffset;

use {
    parking_lot::Mutex,
    std::io::{Read, Seek, Write},
};

fn init_mu() -> Mutex<()> {
    Mutex::new(())
}

type MutexInit = fn() -> Mutex<()>;

static GLOBAL_FILE_LOCK: crate::Lazy<Mutex<()>, MutexInit> =
    crate::Lazy::new(init_mu);

fn pread_exact(
    file: &File,
    mut buf: &mut [u8],
    offset: LogOffset,
) -> io::Result<()> {
    let _lock = GLOBAL_FILE_LOCK.lock();

    let mut f = file.try_clone()?;

    let _ = f.seek(io::SeekFrom::Start(offset))?;

    while !buf.is_empty() {
        match f.read(buf) {
            Ok(0) => break,
            Ok(n) => {
                let tmp = buf;
                buf = &mut tmp[n..];
            }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    if !buf.is_empty() {
        Err(io::Error::new(
            io::ErrorKind::UnexpectedEof,
            "failed to fill whole buffer",
        ))
    } else {
        Ok(())
    }
}

fn pwrite_all(
    file: &File,
    mut buf: &[u8],
    offset: LogOffset,
) -> io::Result<()> {
    let _lock = GLOBAL_FILE_LOCK.lock();

    let mut f = file.try_clone()?;

    let _ = f.seek(io::SeekFrom::Start(offset))?;

    while !buf.is_empty() {
        match f.write(buf) {
            Ok(0) => {
                return Err(io::Error::new(
                    io::ErrorKind::WriteZero,
                    "failed to write whole buffer",
                ));
            }
            Ok(n) => buf = &buf[n..],
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    Ok(())
}
<commit_msg>Add necessary imports<commit_after>use std::fs::File;
use std::io::{self, Read, Seek, Write};

use super::LogOffset;

use {
    parking_lot::Mutex,
    std::io::{Read, Seek, Write},
};

fn init_mu() -> Mutex<()> {
    Mutex::new(())
}

type MutexInit = fn() -> Mutex<()>;

static GLOBAL_FILE_LOCK: crate::Lazy<Mutex<()>, MutexInit> =
    crate::Lazy::new(init_mu);

fn pread_exact(
    file: &File,
    mut buf: &mut [u8],
    offset: LogOffset,
) -> io::Result<()> {
    let _lock = GLOBAL_FILE_LOCK.lock();

    let mut f = file.try_clone()?;

    let _ = f.seek(io::SeekFrom::Start(offset))?;

    while !buf.is_empty() {
        match f.read(buf) {
            Ok(0) => break,
            Ok(n) => {
                let tmp = buf;
                buf = &mut tmp[n..];
            }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    if !buf.is_empty() {
        Err(io::Error::new(
            io::ErrorKind::UnexpectedEof,
            "failed to fill whole buffer",
        ))
    } else {
        Ok(())
    }
}

fn pwrite_all(
    file: &File,
    mut buf: &[u8],
    offset: LogOffset,
) -> io::Result<()> {
    let _lock = GLOBAL_FILE_LOCK.lock();

    let mut f = file.try_clone()?;

    let _ = f.seek(io::SeekFrom::Start(offset))?;

    while !buf.is_empty() {
        match f.write(buf) {
            Ok(0) => {
                return Err(io::Error::new(
                    io::ErrorKind::WriteZero,
                    "failed to write whole buffer",
                ));
            }
            Ok(n) => buf = &buf[n..],
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>use core::sync::atomic::Ordering::SeqCst;
use core::sync::atomic::*;

#[test]
fn bool_() {
    let a = AtomicBool::new(false);
    assert_eq!(a.compare_exchange(false, true, SeqCst, SeqCst), Ok(false));
    assert_eq!(a.compare_exchange(false, true, SeqCst, SeqCst), Err(true));

    a.store(false, SeqCst);
    assert_eq!(a.compare_exchange(false, true, SeqCst, SeqCst), Ok(false));
}

#[test]
fn bool_and() {
    let a = AtomicBool::new(true);
    assert_eq!(a.fetch_and(false, SeqCst), true);
    assert_eq!(a.load(SeqCst), false);
}

#[test]
fn bool_nand() {
    let a = AtomicBool::new(false);
    assert_eq!(a.fetch_nand(false, SeqCst), false);
    assert_eq!(a.load(SeqCst), true);
    assert_eq!(a.fetch_nand(false, SeqCst), true);
    assert_eq!(a.load(SeqCst), true);
    assert_eq!(a.fetch_nand(true, SeqCst), true);
    assert_eq!(a.load(SeqCst), false);
    assert_eq!(a.fetch_nand(true, SeqCst), false);
    assert_eq!(a.load(SeqCst), true);
}

#[test]
fn uint_and() {
    let x = AtomicUsize::new(0xf731);
    assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0xf731 & 0x137f);
}

#[test]
fn uint_nand() {
    let x = AtomicUsize::new(0xf731);
    assert_eq!(x.fetch_nand(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), !(0xf731 & 0x137f));
}

#[test]
fn uint_or() {
    let x = AtomicUsize::new(0xf731);
    assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0xf731 | 0x137f);
}

#[test]
fn uint_xor() {
    let x = AtomicUsize::new(0xf731);
    assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f);
}

#[test]
#[cfg(not(target_arch = "arm"))] // Missing intrinsic in compiler-builtins
fn uint_min() {
    let x = AtomicUsize::new(0xf731);
    assert_eq!(x.fetch_min(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0x137f);
    assert_eq!(x.fetch_min(0xf731, SeqCst), 0x137f);
    assert_eq!(x.load(SeqCst), 0x137f);
}

#[test]
#[cfg(not(target_arch = "arm"))] // Missing intrinsic in compiler-builtins
fn uint_max() {
    let x = AtomicUsize::new(0x137f);
    assert_eq!(x.fetch_max(0xf731, SeqCst), 0x137f);
    assert_eq!(x.load(SeqCst), 0xf731);
    assert_eq!(x.fetch_max(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0xf731);
}

#[test]
fn int_and() {
    let x = AtomicIsize::new(0xf731);
    assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0xf731 & 0x137f);
}

#[test]
fn int_nand() {
    let x = AtomicIsize::new(0xf731);
    assert_eq!(x.fetch_nand(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), !(0xf731 & 0x137f));
}

#[test]
fn int_or() {
    let x = AtomicIsize::new(0xf731);
    assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0xf731 | 0x137f);
}

#[test]
fn int_xor() {
    let x = AtomicIsize::new(0xf731);
    assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f);
}

#[test]
#[cfg(not(target_arch = "arm"))] // Missing intrinsic in compiler-builtins
fn int_min() {
    let x = AtomicIsize::new(0xf731);
    assert_eq!(x.fetch_min(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0x137f);
    assert_eq!(x.fetch_min(0xf731, SeqCst), 0x137f);
    assert_eq!(x.load(SeqCst), 0x137f);
}

#[test]
#[cfg(not(target_arch = "arm"))] // Missing intrinsic in compiler-builtins
fn int_max() {
    let x = AtomicIsize::new(0x137f);
    assert_eq!(x.fetch_max(0xf731, SeqCst), 0x137f);
    assert_eq!(x.load(SeqCst), 0xf731);
    assert_eq!(x.fetch_max(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0xf731);
}

static S_FALSE: AtomicBool = AtomicBool::new(false);
static S_TRUE: AtomicBool = AtomicBool::new(true);
static S_INT: AtomicIsize = AtomicIsize::new(0);
static S_UINT: AtomicUsize = AtomicUsize::new(0);

#[test]
fn static_init() {
    // Note that we're not really testing the mutability here but it's important
    // on Android at the moment (#49775)
    assert!(!S_FALSE.swap(true, SeqCst));
    assert!(S_TRUE.swap(false, SeqCst));
    assert!(S_INT.fetch_add(1, SeqCst) == 0);
    assert!(S_UINT.fetch_add(1, SeqCst) == 0);
}

#[test]
fn atomic_access_bool() {
    static mut ATOMIC: AtomicBool = AtomicBool::new(false);

    unsafe {
        assert_eq!(*ATOMIC.get_mut(), false);
        ATOMIC.store(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_or(false, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_and(false, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), false);
        ATOMIC.fetch_nand(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_xor(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), false);
    }
}

#[test]
fn atomic_alignment() {
    use std::mem::{align_of, size_of};

    #[cfg(target_has_atomic = "8")]
    assert_eq!(align_of::<AtomicBool>(), size_of::<AtomicBool>());
    #[cfg(target_has_atomic = "ptr")]
    assert_eq!(align_of::<AtomicPtr<u8>>(), size_of::<AtomicPtr<u8>>());
    #[cfg(target_has_atomic = "8")]
    assert_eq!(align_of::<AtomicU8>(), size_of::<AtomicU8>());
    #[cfg(target_has_atomic = "8")]
    assert_eq!(align_of::<AtomicI8>(), size_of::<AtomicI8>());
    #[cfg(target_has_atomic = "16")]
    assert_eq!(align_of::<AtomicU16>(), size_of::<AtomicU16>());
    #[cfg(target_has_atomic = "16")]
    assert_eq!(align_of::<AtomicI16>(), size_of::<AtomicI16>());
    #[cfg(target_has_atomic = "32")]
    assert_eq!(align_of::<AtomicU32>(), size_of::<AtomicU32>());
    #[cfg(target_has_atomic = "32")]
    assert_eq!(align_of::<AtomicI32>(), size_of::<AtomicI32>());
    #[cfg(target_has_atomic = "64")]
    assert_eq!(align_of::<AtomicU64>(), size_of::<AtomicU64>());
    #[cfg(target_has_atomic = "64")]
    assert_eq!(align_of::<AtomicI64>(), size_of::<AtomicI64>());
    #[cfg(target_has_atomic = "128")]
    assert_eq!(align_of::<AtomicU128>(), size_of::<AtomicU128>());
    #[cfg(target_has_atomic = "128")]
    assert_eq!(align_of::<AtomicI128>(), size_of::<AtomicI128>());
    #[cfg(target_has_atomic = "ptr")]
    assert_eq!(align_of::<AtomicUsize>(), size_of::<AtomicUsize>());
    #[cfg(target_has_atomic = "ptr")]
    assert_eq!(align_of::<AtomicIsize>(), size_of::<AtomicIsize>());
}

#[test]
fn atomic_compare_exchange() {
    use Ordering::*;

    static ATOMIC: AtomicIsize = AtomicIsize::new(0);

    ATOMIC.compare_exchange(0, 1, Relaxed, Relaxed).ok();
    ATOMIC.compare_exchange(0, 1, Acquire, Relaxed).ok();
    ATOMIC.compare_exchange(0, 1, Release, Relaxed).ok();
    ATOMIC.compare_exchange(0, 1, AcqRel, Relaxed).ok();
    ATOMIC.compare_exchange(0, 1, SeqCst, Relaxed).ok();
    ATOMIC.compare_exchange(0, 1, Acquire, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, AcqRel, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, SeqCst, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, SeqCst, SeqCst).ok();
    ATOMIC.compare_exchange_weak(0, 1, Relaxed, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, Acquire, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, Release, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, AcqRel, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, Acquire, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, AcqRel, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, SeqCst).ok();
}
<commit_msg>Enable the tests on Arm Linux too<commit_after>use core::sync::atomic::Ordering::SeqCst;
use core::sync::atomic::*;

#[test]
fn bool_() {
    let a = AtomicBool::new(false);
    assert_eq!(a.compare_exchange(false, true, SeqCst, SeqCst), Ok(false));
    assert_eq!(a.compare_exchange(false, true, SeqCst, SeqCst), Err(true));

    a.store(false, SeqCst);
    assert_eq!(a.compare_exchange(false, true, SeqCst, SeqCst), Ok(false));
}

#[test]
fn bool_and() {
    let a = AtomicBool::new(true);
    assert_eq!(a.fetch_and(false, SeqCst), true);
    assert_eq!(a.load(SeqCst), false);
}

#[test]
fn bool_nand() {
    let a = AtomicBool::new(false);
    assert_eq!(a.fetch_nand(false, SeqCst), false);
    assert_eq!(a.load(SeqCst), true);
    assert_eq!(a.fetch_nand(false, SeqCst), true);
    assert_eq!(a.load(SeqCst), true);
    assert_eq!(a.fetch_nand(true, SeqCst), true);
    assert_eq!(a.load(SeqCst), false);
    assert_eq!(a.fetch_nand(true, SeqCst), false);
    assert_eq!(a.load(SeqCst), true);
}

#[test]
fn uint_and() {
    let x = AtomicUsize::new(0xf731);
    assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0xf731 & 0x137f);
}

#[test]
fn uint_nand() {
    let x = AtomicUsize::new(0xf731);
    assert_eq!(x.fetch_nand(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), !(0xf731 & 0x137f));
}

#[test]
fn uint_or() {
    let x = AtomicUsize::new(0xf731);
    assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0xf731 | 0x137f);
}

#[test]
fn uint_xor() {
    let x = AtomicUsize::new(0xf731);
    assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f);
}

#[test]
#[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins
fn uint_min() {
    let x = AtomicUsize::new(0xf731);
    assert_eq!(x.fetch_min(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0x137f);
    assert_eq!(x.fetch_min(0xf731, SeqCst), 0x137f);
    assert_eq!(x.load(SeqCst), 0x137f);
}

#[test]
#[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins
fn uint_max() {
    let x = AtomicUsize::new(0x137f);
    assert_eq!(x.fetch_max(0xf731, SeqCst), 0x137f);
    assert_eq!(x.load(SeqCst), 0xf731);
    assert_eq!(x.fetch_max(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0xf731);
}

#[test]
fn int_and() {
    let x = AtomicIsize::new(0xf731);
    assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0xf731 & 0x137f);
}

#[test]
fn int_nand() {
    let x = AtomicIsize::new(0xf731);
    assert_eq!(x.fetch_nand(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), !(0xf731 & 0x137f));
}

#[test]
fn int_or() {
    let x = AtomicIsize::new(0xf731);
    assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0xf731 | 0x137f);
}

#[test]
fn int_xor() {
    let x = AtomicIsize::new(0xf731);
    assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f);
}

#[test]
#[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins
fn int_min() {
    let x = AtomicIsize::new(0xf731);
    assert_eq!(x.fetch_min(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0x137f);
    assert_eq!(x.fetch_min(0xf731, SeqCst), 0x137f);
    assert_eq!(x.load(SeqCst), 0x137f);
}

#[test]
#[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins
fn int_max() {
    let x = AtomicIsize::new(0x137f);
    assert_eq!(x.fetch_max(0xf731, SeqCst), 0x137f);
    assert_eq!(x.load(SeqCst), 0xf731);
    assert_eq!(x.fetch_max(0x137f, SeqCst), 0xf731);
    assert_eq!(x.load(SeqCst), 0xf731);
}

static S_FALSE: AtomicBool = AtomicBool::new(false);
static S_TRUE: AtomicBool = AtomicBool::new(true);
static S_INT: AtomicIsize = AtomicIsize::new(0);
static S_UINT: AtomicUsize = AtomicUsize::new(0);

#[test]
fn static_init() {
    // Note that we're not really testing the mutability here but it's important
    // on Android at the moment (#49775)
    assert!(!S_FALSE.swap(true, SeqCst));
    assert!(S_TRUE.swap(false, SeqCst));
    assert!(S_INT.fetch_add(1, SeqCst) == 0);
    assert!(S_UINT.fetch_add(1, SeqCst) == 0);
}

#[test]
fn atomic_access_bool() {
    static mut ATOMIC: AtomicBool = AtomicBool::new(false);

    unsafe {
        assert_eq!(*ATOMIC.get_mut(), false);
        ATOMIC.store(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_or(false, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_and(false, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), false);
        ATOMIC.fetch_nand(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), true);
        ATOMIC.fetch_xor(true, SeqCst);
        assert_eq!(*ATOMIC.get_mut(), false);
    }
}

#[test]
fn atomic_alignment() {
    use std::mem::{align_of, size_of};

    #[cfg(target_has_atomic = "8")]
    assert_eq!(align_of::<AtomicBool>(), size_of::<AtomicBool>());
    #[cfg(target_has_atomic = "ptr")]
    assert_eq!(align_of::<AtomicPtr<u8>>(), size_of::<AtomicPtr<u8>>());
    #[cfg(target_has_atomic = "8")]
    assert_eq!(align_of::<AtomicU8>(), size_of::<AtomicU8>());
    #[cfg(target_has_atomic = "8")]
    assert_eq!(align_of::<AtomicI8>(), size_of::<AtomicI8>());
    #[cfg(target_has_atomic = "16")]
    assert_eq!(align_of::<AtomicU16>(), size_of::<AtomicU16>());
    #[cfg(target_has_atomic = "16")]
    assert_eq!(align_of::<AtomicI16>(), size_of::<AtomicI16>());
    #[cfg(target_has_atomic = "32")]
    assert_eq!(align_of::<AtomicU32>(), size_of::<AtomicU32>());
    #[cfg(target_has_atomic = "32")]
    assert_eq!(align_of::<AtomicI32>(), size_of::<AtomicI32>());
    #[cfg(target_has_atomic = "64")]
    assert_eq!(align_of::<AtomicU64>(), size_of::<AtomicU64>());
    #[cfg(target_has_atomic = "64")]
    assert_eq!(align_of::<AtomicI64>(), size_of::<AtomicI64>());
    #[cfg(target_has_atomic = "128")]
    assert_eq!(align_of::<AtomicU128>(), size_of::<AtomicU128>());
    #[cfg(target_has_atomic = "128")]
    assert_eq!(align_of::<AtomicI128>(), size_of::<AtomicI128>());
    #[cfg(target_has_atomic = "ptr")]
    assert_eq!(align_of::<AtomicUsize>(), size_of::<AtomicUsize>());
    #[cfg(target_has_atomic = "ptr")]
    assert_eq!(align_of::<AtomicIsize>(), size_of::<AtomicIsize>());
}

#[test]
fn atomic_compare_exchange() {
    use Ordering::*;

    static ATOMIC: AtomicIsize = AtomicIsize::new(0);

    ATOMIC.compare_exchange(0, 1, Relaxed, Relaxed).ok();
    ATOMIC.compare_exchange(0, 1, Acquire, Relaxed).ok();
    ATOMIC.compare_exchange(0, 1, Release, Relaxed).ok();
    ATOMIC.compare_exchange(0, 1, AcqRel, Relaxed).ok();
    ATOMIC.compare_exchange(0, 1, SeqCst, Relaxed).ok();
    ATOMIC.compare_exchange(0, 1, Acquire, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, AcqRel, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, SeqCst, Acquire).ok();
    ATOMIC.compare_exchange(0, 1, SeqCst, SeqCst).ok();
    ATOMIC.compare_exchange_weak(0, 1, Relaxed, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, Acquire, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, Release, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, AcqRel, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, Relaxed).ok();
    ATOMIC.compare_exchange_weak(0, 1, Acquire, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, AcqRel, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, Acquire).ok();
    ATOMIC.compare_exchange_weak(0, 1, SeqCst, SeqCst).ok();
}
<|endoftext|>


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

struct S(String);

impl S {
    fn f(self: *mut S) -> String { self.0 }
    //~^ ERROR raw pointer `self` is unstable
}

fn main() { S("".to_owned()).f(); }
<commit_msg>remove test for issue #26194 because it is now redundant<commit_after><|endoftext|>


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

#![feature(closure_to_fn_coercion)]

fn main() {
    let bar: fn(&mut u32) = |_| {}; //~ ERROR mismatched types
    //~| expected concrete lifetime, found bound lifetime parameter

    fn foo(x: Box<Fn(&i32)>) {}
    let bar = Box::new(|x: &i32| {}) as Box<Fn(_)>;
    foo(bar); //~ ERROR mismatched types
    //~| expected concrete lifetime, found bound lifetime parameter
}
<commit_msg>first part of issue-40000.rs is now passing<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(closure_to_fn_coercion)]

fn main() {
    let bar: fn(&mut u32) = |_| {};

    fn foo(x: Box<Fn(&i32)>) {}
    let bar = Box::new(|x: &i32| {}) as Box<Fn(_)>;
    foo(bar); //~ ERROR mismatched types
    //~| expected concrete lifetime, found bound lifetime parameter
}
<|endoftext|>


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

// ignore-windows
// ignore-android
// ignore-emscripten

#![feature(libc)]

extern crate libc;

use std::env;
use std::fs::File;
use std::io;
use std::net::{TcpListener, TcpStream, UdpSocket};
use std::os::unix::prelude::*;
use std::process::{Command, Stdio};
use std::thread;

fn main() {
    let args = env::args().collect::<Vec<_>>();
    if args.len() == 1 {
        parent()
    } else {
        child(&args)
    }
}

fn parent() {
    let file = File::open("Makefile").unwrap();
    let tcp1 = TcpListener::bind("127.0.0.1:0").unwrap();
    let tcp2 = tcp1.try_clone().unwrap();
    let addr = tcp1.local_addr().unwrap();
    let t = thread::spawn(move || TcpStream::connect(addr).unwrap());
    let tcp3 = tcp1.accept().unwrap().0;
    let tcp4 = t.join().unwrap();
    let tcp5 = tcp3.try_clone().unwrap();
    let tcp6 = tcp4.try_clone().unwrap();
    let udp1 = UdpSocket::bind("127.0.0.1:0").unwrap();
    let udp2 = udp1.try_clone().unwrap();

    let mut child = Command::new(env::args().next().unwrap())
                            .arg("100")
                            .stdout(Stdio::piped())
                            .stdin(Stdio::piped())
                            .stderr(Stdio::piped())
                            .spawn().unwrap();
    let pipe1 = child.stdin.take().unwrap();
    let pipe2 = child.stdout.take().unwrap();
    let pipe3 = child.stderr.take().unwrap();

    let status = Command::new(env::args().next().unwrap())
                        .arg(file.as_raw_fd().to_string())
                        .arg(tcp1.as_raw_fd().to_string())
                        .arg(tcp2.as_raw_fd().to_string())
                        .arg(tcp3.as_raw_fd().to_string())
                        .arg(tcp4.as_raw_fd().to_string())
                        .arg(tcp5.as_raw_fd().to_string())
                        .arg(tcp6.as_raw_fd().to_string())
                        .arg(udp1.as_raw_fd().to_string())
                        .arg(udp2.as_raw_fd().to_string())
                        .arg(pipe1.as_raw_fd().to_string())
                        .arg(pipe2.as_raw_fd().to_string())
                        .arg(pipe3.as_raw_fd().to_string())
                        .status()
                        .unwrap();
    assert!(status.success());
    child.wait().unwrap();
}

fn child(args: &[String]) {
    let mut b = [0u8; 2];
    for arg in &args[1..] {
        let fd: libc::c_int = arg.parse().unwrap();
        unsafe {
            assert_eq!(libc::read(fd, b.as_mut_ptr() as *mut _, 2), -1);
            assert_eq!(io::Error::last_os_error().raw_os_error(),
                       Some(libc::EBADF));
        }
    }
}
<commit_msg>modify fds-are-cloexec test to open a file that exists<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-windows
// ignore-android
// ignore-emscripten

#![feature(libc)]

extern crate libc;

use std::env;
use std::fs::File;
use std::io;
use std::net::{TcpListener, TcpStream, UdpSocket};
use std::os::unix::prelude::*;
use std::process::{Command, Stdio};
use std::thread;

fn main() {
    let args = env::args().collect::<Vec<_>>();
    if args.len() == 1 {
        parent()
    } else {
        child(&args)
    }
}

fn parent() {
    let file = File::open("src/test/run-pass/fds-are-cloexec.rs").unwrap();
    let tcp1 = TcpListener::bind("127.0.0.1:0").unwrap();
    let tcp2 = tcp1.try_clone().unwrap();
    let addr = tcp1.local_addr().unwrap();
    let t = thread::spawn(move || TcpStream::connect(addr).unwrap());
    let tcp3 = tcp1.accept().unwrap().0;
    let tcp4 = t.join().unwrap();
    let tcp5 = tcp3.try_clone().unwrap();
    let tcp6 = tcp4.try_clone().unwrap();
    let udp1 = UdpSocket::bind("127.0.0.1:0").unwrap();
    let udp2 = udp1.try_clone().unwrap();

    let mut child = Command::new(env::args().next().unwrap())
                            .arg("100")
                            .stdout(Stdio::piped())
                            .stdin(Stdio::piped())
                            .stderr(Stdio::piped())
                            .spawn().unwrap();
    let pipe1 = child.stdin.take().unwrap();
    let pipe2 = child.stdout.take().unwrap();
    let pipe3 = child.stderr.take().unwrap();

    let status = Command::new(env::args().next().unwrap())
                        .arg(file.as_raw_fd().to_string())
                        .arg(tcp1.as_raw_fd().to_string())
                        .arg(tcp2.as_raw_fd().to_string())
                        .arg(tcp3.as_raw_fd().to_string())
                        .arg(tcp4.as_raw_fd().to_string())
                        .arg(tcp5.as_raw_fd().to_string())
                        .arg(tcp6.as_raw_fd().to_string())
                        .arg(udp1.as_raw_fd().to_string())
                        .arg(udp2.as_raw_fd().to_string())
                        .arg(pipe1.as_raw_fd().to_string())
                        .arg(pipe2.as_raw_fd().to_string())
                        .arg(pipe3.as_raw_fd().to_string())
                        .status()
                        .unwrap();
    assert!(status.success());
    child.wait().unwrap();
}

fn child(args: &[String]) {
    let mut b = [0u8; 2];
    for arg in &args[1..] {
        let fd: libc::c_int = arg.parse().unwrap();
        unsafe {
            assert_eq!(libc::read(fd, b.as_mut_ptr() as *mut _, 2), -1);
            assert_eq!(io::Error::last_os_error().raw_os_error(),
                       Some(libc::EBADF));
        }
    }
}
<|endoftext|>