<commit_before>use super::super::{Device, RawDevice, RawSurface, Surface};
use super::error::*;

use drm::control::{connector, crtc, framebuffer, Mode, ResourceHandles, ResourceInfo};
use gbm::{self, BufferObject, BufferObjectFlags, Format as GbmFormat, SurfaceBufferHandle};
use image::{ImageBuffer, Rgba};

use std::cell::{Cell, RefCell};
use std::os::unix::io::AsRawFd;
use std::rc::Rc;

use backend::drm::legacy::LegacyDrmDevice;
use backend::graphics::CursorBackend;
use backend::graphics::SwapBuffersError;

pub(super) struct GbmSurfaceInternal<D: RawDevice + 'static> {
    pub(super) dev: Rc<RefCell<gbm::Device<D>>>,
    pub(super) surface: RefCell<gbm::Surface<framebuffer::Info>>,
    pub(super) crtc: <D as Device>::Surface,
    pub(super) cursor: Cell<(BufferObject<()>, (u32, u32))>,
    pub(super) current_frame_buffer: Cell<framebuffer::Info>,
    pub(super) front_buffer: Cell<SurfaceBufferHandle<framebuffer::Info>>,
    pub(super) next_buffer: Cell<Option<SurfaceBufferHandle<framebuffer::Info>>>,
    pub(super) logger: ::slog::Logger,
}

impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
    pub(super) fn unlock_buffer(&self) {
        // after the page swap is finished we need to release the rendered buffer.
        // this is called from the PageFlipHandler
        if let Some(next_buffer) = self.next_buffer.replace(None) {
            trace!(self.logger, "Releasing old front buffer");
            self.front_buffer.set(next_buffer);
            // drop and release the old buffer
        }
    }

    pub fn page_flip<F>(&self, flip: F) -> ::std::result::Result<(), SwapBuffersError>
    where
        F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>,
    {
        let res = {
            let nb = self.next_buffer.take();
            let res = nb.is_some();
            self.next_buffer.set(nb);
            res
        };
        if res {
            // We cannot call lock_front_buffer anymore without releasing the previous buffer, which will happen when the page flip is done
            warn!(self.logger, "Tried to swap with an already queued flip");
            return Err(SwapBuffersError::AlreadySwapped);
        }

        // flip normally
        flip()?;

        // supporting only one buffer would cause a lot of inconvinience and
        // would most likely result in a lot of flickering.
        // neither weston, wlc or wlroots bother with that as well.
        // so we just assume we got at least two buffers to do flipping.
        let mut next_bo = self
            .surface
            .borrow()
            .lock_front_buffer()
            .expect("Surface only has one front buffer. Not supported by smithay");

        // create a framebuffer if the front buffer does not have one already
        // (they are reused by gbm)
        let maybe_fb = next_bo
            .userdata()
            .map_err(|_| SwapBuffersError::ContextLost)?
            .cloned();
        let fb = if let Some(info) = maybe_fb {
            info
        } else {
            let fb = framebuffer::create(&self.crtc, &*next_bo).map_err(|_| SwapBuffersError::ContextLost)?;
            next_bo.set_userdata(fb).unwrap();
            fb
        };
        self.next_buffer.set(Some(next_bo));

        trace!(self.logger, "Queueing Page flip");
        self.crtc.page_flip(fb.handle())?;

        self.current_frame_buffer.set(fb);

        Ok(())
    }

    pub fn recreate<F>(&self, flip: F) -> Result<()>
    where
        F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>,
    {
        let (w, h) = self.pending_mode().size();

        // Recreate the surface and the related resources to match the new
        // resolution.
        debug!(self.logger, "Reinitializing surface for new mode: {}:{}", w, h);
        let surface = self
            .dev
            .borrow_mut()
            .create_surface(
                w as u32,
                h as u32,
                GbmFormat::XRGB8888,
                BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING,
            ).chain_err(|| ErrorKind::SurfaceCreationFailed)?;

        flip()?;

        // Clean up next_buffer
        {
            if let Some(mut old_bo) = self.next_buffer.take() {
                if let Ok(Some(fb)) = old_bo.take_userdata() {
                    if let Err(err) = framebuffer::destroy(&self.crtc, fb.handle()) {
                        warn!(
                            self.logger,
                            "Error releasing old back_buffer framebuffer: {:?}", err
                        );
                    }
                }
            }
        }

        // Cleanup front_buffer and init the first screen on the new front_buffer
        // (must be done before calling page_flip for the first time)
        let mut old_front_bo = self.front_buffer.replace({
            let mut front_bo = surface
                .lock_front_buffer()
                .chain_err(|| ErrorKind::FrontBufferLockFailed)?;

            debug!(self.logger, "FrontBuffer color format: {:?}", front_bo.format());

            // we also need a new framebuffer for the front buffer
            let fb = framebuffer::create(&self.crtc, &*front_bo)
                .chain_err(|| ErrorKind::UnderlyingBackendError)?;

            self.crtc
                .commit(fb.handle())
                .chain_err(|| ErrorKind::UnderlyingBackendError)?;

            front_bo.set_userdata(fb).unwrap();
            front_bo
        });
        if let Ok(Some(fb)) = old_front_bo.take_userdata() {
            if let Err(err) = framebuffer::destroy(&self.crtc, fb.handle()) {
                warn!(
                    self.logger,
                    "Error releasing old front_buffer framebuffer: {:?}", err
                );
            }
        }

        // Drop the old surface after cleanup
        *self.surface.borrow_mut() = surface;

        Ok(())
    }
}

impl<D: RawDevice + 'static> Surface for GbmSurfaceInternal<D> {
    type Connectors = <<D as Device>::Surface as Surface>::Connectors;
    type Error = Error;

    fn crtc(&self) -> crtc::Handle {
        self.crtc.crtc()
    }

    fn current_connectors(&self) -> Self::Connectors {
        self.crtc.current_connectors()
    }

    fn pending_connectors(&self) -> Self::Connectors {
        self.crtc.pending_connectors()
    }

    fn add_connector(&self, connector: connector::Handle) -> Result<()> {
        self.crtc
            .add_connector(connector)
            .chain_err(|| ErrorKind::UnderlyingBackendError)
    }

    fn remove_connector(&self, connector: connector::Handle) -> Result<()> {
        self.crtc
            .remove_connector(connector)
            .chain_err(|| ErrorKind::UnderlyingBackendError)
    }

    fn current_mode(&self) -> Mode {
        self.crtc.current_mode()
    }

    fn pending_mode(&self) -> Mode {
        self.crtc.pending_mode()
    }

    fn use_mode(&self, mode: Mode) -> Result<()> {
        self.crtc
            .use_mode(mode)
            .chain_err(|| ErrorKind::UnderlyingBackendError)
    }
}

// FIXME:
//
// Option 1: When there is GAT support, impl `GraphicsBackend` for `LegacyDrmBackend`
//           using a new generic `B: Buffer` and use this:
/*
impl<'a, D: RawDevice + 'static> CursorBackend<'a> for GbmSurfaceInternal<D>
where
    <D as RawDevice>::Surface: CursorBackend<'a>,
    <<D as RawDevice>::Surface as CursorBackend<'a>>::CursorFormat: Buffer,
    <<D as RawDevice>::Surface as CursorBackend<'a>>::Error: ::std::error::Error + Send
{
*/
//
// Option 2: When equality checks in where clauses are supported, we could at least do this:
/*
impl<'a, D: RawDevice + 'static> GraphicsBackend<'a> for GbmSurfaceInternal<D>
where
    <D as RawDevice>::Surface: CursorBackend<'a>,
    <<D as RawDevice>::Surface as CursorBackend<'a>>::CursorFormat=&'a Buffer,
    <<D as RawDevice>::Surface as CursorBackend<'a>>::Error: ::std::error::Error + Send
{
*/
// But for now got to do this:

impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for GbmSurfaceInternal<LegacyDrmDevice<A>> {
    type CursorFormat = &'a ImageBuffer<Rgba<u8>, Vec<u8>>;
    type Error = Error;

    fn set_cursor_position(&self, x: u32, y: u32) -> Result<()> {
        ResultExt::chain_err(self.crtc.set_cursor_position(x, y), || {
            ErrorKind::UnderlyingBackendError
        })
    }

    fn set_cursor_representation<'b>(
        &'b self,
        buffer: &ImageBuffer<Rgba<u8>, Vec<u8>>,
        hotspot: (u32, u32),
    ) -> Result<()>
    where
        'a: 'b,
    {
        let (w, h) = buffer.dimensions();
        debug!(self.logger, "Importing cursor");

        // import the cursor into a buffer we can render
        let mut cursor = self
            .dev
            .borrow_mut()
            .create_buffer_object(
                w,
                h,
                GbmFormat::ARGB8888,
                BufferObjectFlags::CURSOR | BufferObjectFlags::WRITE,
            ).chain_err(|| ErrorKind::BufferCreationFailed)?;

        cursor
            .write(&**buffer)
            .chain_err(|| ErrorKind::BufferWriteFailed)?
            .chain_err(|| ErrorKind::BufferWriteFailed)?;

        trace!(self.logger, "Setting the new imported cursor");

        ResultExt::chain_err(self.crtc.set_cursor_representation(&cursor, hotspot), || {
            ErrorKind::UnderlyingBackendError
        })?;

        // and store it
        self.cursor.set((cursor, hotspot));
        Ok(())
    }
}

impl<D: RawDevice + 'static> Drop for GbmSurfaceInternal<D> {
    fn drop(&mut self) {
        // Drop framebuffers attached to the userdata of the gbm surface buffers.
        // (They don't implement drop, as they need the device)
        if let Ok(Some(fb)) = {
            if let Some(mut next) = self.next_buffer.take() {
                next.take_userdata()
            } else if let Ok(mut next) = self.surface.borrow().lock_front_buffer() {
                next.take_userdata()
            } else {
                Ok(None)
            }
        } {
            // ignore failure at this point
            let _ = framebuffer::destroy(&self.crtc, fb.handle());
        }

        if let Ok(Some(fb)) = self.front_buffer.get_mut().take_userdata() {
            // ignore failure at this point
            let _ = framebuffer::destroy(&self.crtc, fb.handle());
        }
    }
}

pub struct GbmSurface<D: RawDevice + 'static>(pub(super) Rc<GbmSurfaceInternal<D>>);

impl<D: RawDevice + 'static> GbmSurface<D> {
    pub fn page_flip<F>(&self, flip: F) -> ::std::result::Result<(), SwapBuffersError>
    where
        F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>,
    {
        self.0.page_flip(flip)
    }

    pub fn recreate<F>(&self, flip: F) -> Result<()>
    where
        F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>,
    {
        self.0.recreate(flip)
    }
}

impl<D: RawDevice + 'static> Surface for GbmSurface<D> {
    type Connectors = <<D as Device>::Surface as Surface>::Connectors;
    type Error = Error;

    fn crtc(&self) -> crtc::Handle {
        self.0.crtc()
    }

    fn current_connectors(&self) -> Self::Connectors {
        self.0.current_connectors()
    }

    fn pending_connectors(&self) -> Self::Connectors {
        self.0.pending_connectors()
    }

    fn add_connector(&self, connector: connector::Handle) -> Result<()> {
        self.0.add_connector(connector)
    }

    fn remove_connector(&self, connector: connector::Handle) -> Result<()> {
        self.0.remove_connector(connector)
    }

    fn current_mode(&self) -> Mode {
        self.0.current_mode()
    }

    fn pending_mode(&self) -> Mode {
        self.0.pending_mode()
    }

    fn use_mode(&self, mode: Mode) -> Result<()> {
        self.0.use_mode(mode)
    }
}

impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for GbmSurface<LegacyDrmDevice<A>> {
    type CursorFormat = &'a ImageBuffer<Rgba<u8>, Vec<u8>>;
    type Error = Error;

    fn set_cursor_position(&self, x: u32, y: u32) -> Result<()> {
        self.0.set_cursor_position(x, y)
    }

    fn set_cursor_representation<'b>(
        &'b self,
        buffer: &ImageBuffer<Rgba<u8>, Vec<u8>>,
        hotspot: (u32, u32),
    ) -> Result<()>
    where
        'a: 'b,
    {
        self.0.set_cursor_representation(buffer, hotspot)
    }
}
<commit_msg>gbm: CursorBackend depends on backend_drm_legacy<commit_after>use super::super::{Device, RawDevice, RawSurface, Surface};
use super::error::*;

use drm::control::{connector, crtc, framebuffer, Mode, ResourceHandles, ResourceInfo};
use gbm::{self, BufferObject, BufferObjectFlags, Format as GbmFormat, SurfaceBufferHandle};
use image::{ImageBuffer, Rgba};

use std::cell::{Cell, RefCell};
use std::os::unix::io::AsRawFd;
use std::rc::Rc;

#[cfg(feature = "backend_drm_legacy")]
use backend::drm::legacy::LegacyDrmDevice;
use backend::graphics::CursorBackend;
use backend::graphics::SwapBuffersError;

pub(super) struct GbmSurfaceInternal<D: RawDevice + 'static> {
    pub(super) dev: Rc<RefCell<gbm::Device<D>>>,
    pub(super) surface: RefCell<gbm::Surface<framebuffer::Info>>,
    pub(super) crtc: <D as Device>::Surface,
    pub(super) cursor: Cell<(BufferObject<()>, (u32, u32))>,
    pub(super) current_frame_buffer: Cell<framebuffer::Info>,
    pub(super) front_buffer: Cell<SurfaceBufferHandle<framebuffer::Info>>,
    pub(super) next_buffer: Cell<Option<SurfaceBufferHandle<framebuffer::Info>>>,
    pub(super) logger: ::slog::Logger,
}

impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
    pub(super) fn unlock_buffer(&self) {
        // after the page swap is finished we need to release the rendered buffer.
        // this is called from the PageFlipHandler
        if let Some(next_buffer) = self.next_buffer.replace(None) {
            trace!(self.logger, "Releasing old front buffer");
            self.front_buffer.set(next_buffer);
            // drop and release the old buffer
        }
    }

    pub fn page_flip<F>(&self, flip: F) -> ::std::result::Result<(), SwapBuffersError>
    where
        F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>,
    {
        let res = {
            let nb = self.next_buffer.take();
            let res = nb.is_some();
            self.next_buffer.set(nb);
            res
        };
        if res {
            // We cannot call lock_front_buffer anymore without releasing the previous buffer, which will happen when the page flip is done
            warn!(self.logger, "Tried to swap with an already queued flip");
            return Err(SwapBuffersError::AlreadySwapped);
        }

        // flip normally
        flip()?;

        // supporting only one buffer would cause a lot of inconvinience and
        // would most likely result in a lot of flickering.
        // neither weston, wlc or wlroots bother with that as well.
        // so we just assume we got at least two buffers to do flipping.
        let mut next_bo = self
            .surface
            .borrow()
            .lock_front_buffer()
            .expect("Surface only has one front buffer. Not supported by smithay");

        // create a framebuffer if the front buffer does not have one already
        // (they are reused by gbm)
        let maybe_fb = next_bo
            .userdata()
            .map_err(|_| SwapBuffersError::ContextLost)?
            .cloned();
        let fb = if let Some(info) = maybe_fb {
            info
        } else {
            let fb = framebuffer::create(&self.crtc, &*next_bo).map_err(|_| SwapBuffersError::ContextLost)?;
            next_bo.set_userdata(fb).unwrap();
            fb
        };
        self.next_buffer.set(Some(next_bo));

        trace!(self.logger, "Queueing Page flip");
        self.crtc.page_flip(fb.handle())?;

        self.current_frame_buffer.set(fb);

        Ok(())
    }

    pub fn recreate<F>(&self, flip: F) -> Result<()>
    where
        F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>,
    {
        let (w, h) = self.pending_mode().size();

        // Recreate the surface and the related resources to match the new
        // resolution.
        debug!(self.logger, "Reinitializing surface for new mode: {}:{}", w, h);
        let surface = self
            .dev
            .borrow_mut()
            .create_surface(
                w as u32,
                h as u32,
                GbmFormat::XRGB8888,
                BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING,
            ).chain_err(|| ErrorKind::SurfaceCreationFailed)?;

        flip()?;

        // Clean up next_buffer
        {
            if let Some(mut old_bo) = self.next_buffer.take() {
                if let Ok(Some(fb)) = old_bo.take_userdata() {
                    if let Err(err) = framebuffer::destroy(&self.crtc, fb.handle()) {
                        warn!(
                            self.logger,
                            "Error releasing old back_buffer framebuffer: {:?}", err
                        );
                    }
                }
            }
        }

        // Cleanup front_buffer and init the first screen on the new front_buffer
        // (must be done before calling page_flip for the first time)
        let mut old_front_bo = self.front_buffer.replace({
            let mut front_bo = surface
                .lock_front_buffer()
                .chain_err(|| ErrorKind::FrontBufferLockFailed)?;

            debug!(self.logger, "FrontBuffer color format: {:?}", front_bo.format());

            // we also need a new framebuffer for the front buffer
            let fb = framebuffer::create(&self.crtc, &*front_bo)
                .chain_err(|| ErrorKind::UnderlyingBackendError)?;

            self.crtc
                .commit(fb.handle())
                .chain_err(|| ErrorKind::UnderlyingBackendError)?;

            front_bo.set_userdata(fb).unwrap();
            front_bo
        });
        if let Ok(Some(fb)) = old_front_bo.take_userdata() {
            if let Err(err) = framebuffer::destroy(&self.crtc, fb.handle()) {
                warn!(
                    self.logger,
                    "Error releasing old front_buffer framebuffer: {:?}", err
                );
            }
        }

        // Drop the old surface after cleanup
        *self.surface.borrow_mut() = surface;

        Ok(())
    }
}

impl<D: RawDevice + 'static> Surface for GbmSurfaceInternal<D> {
    type Connectors = <<D as Device>::Surface as Surface>::Connectors;
    type Error = Error;

    fn crtc(&self) -> crtc::Handle {
        self.crtc.crtc()
    }

    fn current_connectors(&self) -> Self::Connectors {
        self.crtc.current_connectors()
    }

    fn pending_connectors(&self) -> Self::Connectors {
        self.crtc.pending_connectors()
    }

    fn add_connector(&self, connector: connector::Handle) -> Result<()> {
        self.crtc
            .add_connector(connector)
            .chain_err(|| ErrorKind::UnderlyingBackendError)
    }

    fn remove_connector(&self, connector: connector::Handle) -> Result<()> {
        self.crtc
            .remove_connector(connector)
            .chain_err(|| ErrorKind::UnderlyingBackendError)
    }

    fn current_mode(&self) -> Mode {
        self.crtc.current_mode()
    }

    fn pending_mode(&self) -> Mode {
        self.crtc.pending_mode()
    }

    fn use_mode(&self, mode: Mode) -> Result<()> {
        self.crtc
            .use_mode(mode)
            .chain_err(|| ErrorKind::UnderlyingBackendError)
    }
}

// FIXME:
//
// Option 1: When there is GAT support, impl `GraphicsBackend` for `LegacyDrmBackend`
//           using a new generic `B: Buffer` and use this:
/*
impl<'a, D: RawDevice + 'static> CursorBackend<'a> for GbmSurfaceInternal<D>
where
    <D as RawDevice>::Surface: CursorBackend<'a>,
    <<D as RawDevice>::Surface as CursorBackend<'a>>::CursorFormat: Buffer,
    <<D as RawDevice>::Surface as CursorBackend<'a>>::Error: ::std::error::Error + Send
{
*/
//
// Option 2: When equality checks in where clauses are supported, we could at least do this:
/*
impl<'a, D: RawDevice + 'static> GraphicsBackend<'a> for GbmSurfaceInternal<D>
where
    <D as RawDevice>::Surface: CursorBackend<'a>,
    <<D as RawDevice>::Surface as CursorBackend<'a>>::CursorFormat=&'a Buffer,
    <<D as RawDevice>::Surface as CursorBackend<'a>>::Error: ::std::error::Error + Send
{
*/
// But for now got to do this:

#[cfg(feature = "backend_drm_legacy")]
impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for GbmSurfaceInternal<LegacyDrmDevice<A>> {
    type CursorFormat = &'a ImageBuffer<Rgba<u8>, Vec<u8>>;
    type Error = Error;

    fn set_cursor_position(&self, x: u32, y: u32) -> Result<()> {
        ResultExt::chain_err(self.crtc.set_cursor_position(x, y), || {
            ErrorKind::UnderlyingBackendError
        })
    }

    fn set_cursor_representation<'b>(
        &'b self,
        buffer: &ImageBuffer<Rgba<u8>, Vec<u8>>,
        hotspot: (u32, u32),
    ) -> Result<()>
    where
        'a: 'b,
    {
        let (w, h) = buffer.dimensions();
        debug!(self.logger, "Importing cursor");

        // import the cursor into a buffer we can render
        let mut cursor = self
            .dev
            .borrow_mut()
            .create_buffer_object(
                w,
                h,
                GbmFormat::ARGB8888,
                BufferObjectFlags::CURSOR | BufferObjectFlags::WRITE,
            ).chain_err(|| ErrorKind::BufferCreationFailed)?;

        cursor
            .write(&**buffer)
            .chain_err(|| ErrorKind::BufferWriteFailed)?
            .chain_err(|| ErrorKind::BufferWriteFailed)?;

        trace!(self.logger, "Setting the new imported cursor");

        ResultExt::chain_err(self.crtc.set_cursor_representation(&cursor, hotspot), || {
            ErrorKind::UnderlyingBackendError
        })?;

        // and store it
        self.cursor.set((cursor, hotspot));
        Ok(())
    }
}

impl<D: RawDevice + 'static> Drop for GbmSurfaceInternal<D> {
    fn drop(&mut self) {
        // Drop framebuffers attached to the userdata of the gbm surface buffers.
        // (They don't implement drop, as they need the device)
        if let Ok(Some(fb)) = {
            if let Some(mut next) = self.next_buffer.take() {
                next.take_userdata()
            } else if let Ok(mut next) = self.surface.borrow().lock_front_buffer() {
                next.take_userdata()
            } else {
                Ok(None)
            }
        } {
            // ignore failure at this point
            let _ = framebuffer::destroy(&self.crtc, fb.handle());
        }

        if let Ok(Some(fb)) = self.front_buffer.get_mut().take_userdata() {
            // ignore failure at this point
            let _ = framebuffer::destroy(&self.crtc, fb.handle());
        }
    }
}

pub struct GbmSurface<D: RawDevice + 'static>(pub(super) Rc<GbmSurfaceInternal<D>>);

impl<D: RawDevice + 'static> GbmSurface<D> {
    pub fn page_flip<F>(&self, flip: F) -> ::std::result::Result<(), SwapBuffersError>
    where
        F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>,
    {
        self.0.page_flip(flip)
    }

    pub fn recreate<F>(&self, flip: F) -> Result<()>
    where
        F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>,
    {
        self.0.recreate(flip)
    }
}

impl<D: RawDevice + 'static> Surface for GbmSurface<D> {
    type Connectors = <<D as Device>::Surface as Surface>::Connectors;
    type Error = Error;

    fn crtc(&self) -> crtc::Handle {
        self.0.crtc()
    }

    fn current_connectors(&self) -> Self::Connectors {
        self.0.current_connectors()
    }

    fn pending_connectors(&self) -> Self::Connectors {
        self.0.pending_connectors()
    }

    fn add_connector(&self, connector: connector::Handle) -> Result<()> {
        self.0.add_connector(connector)
    }

    fn remove_connector(&self, connector: connector::Handle) -> Result<()> {
        self.0.remove_connector(connector)
    }

    fn current_mode(&self) -> Mode {
        self.0.current_mode()
    }

    fn pending_mode(&self) -> Mode {
        self.0.pending_mode()
    }

    fn use_mode(&self, mode: Mode) -> Result<()> {
        self.0.use_mode(mode)
    }
}

#[cfg(feature = "backend_drm_legacy")]
impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for GbmSurface<LegacyDrmDevice<A>> {
    type CursorFormat = &'a ImageBuffer<Rgba<u8>, Vec<u8>>;
    type Error = Error;

    fn set_cursor_position(&self, x: u32, y: u32) -> Result<()> {
        self.0.set_cursor_position(x, y)
    }

    fn set_cursor_representation<'b>(
        &'b self,
        buffer: &ImageBuffer<Rgba<u8>, Vec<u8>>,
        hotspot: (u32, u32),
    ) -> Result<()>
    where
        'a: 'b,
    {
        self.0.set_cursor_representation(buffer, hotspot)
    }
}
<|endoftext|>


<commit_before>use protobuf::rustproto;
use protobuf::descriptor::FieldOptions;
use protobuf::descriptor::MessageOptions;
use protobuf::descriptor::FileOptions;

/// Specifies style of generated code.
/// Generated files can be customized using this proto
/// or using `rustproto.proto` options.
#[derive(Default, Debug, Clone)]
pub struct Customize {
    /// Make oneof enum public.
    pub expose_oneof: Option<bool>,
    /// When true all fields are public, and accessors are not generated
    pub expose_fields: Option<bool>,
    /// When false, `get_`, `set_`, `mut_` etc. accessors are not generated
    pub generate_accessors: Option<bool>,
    /// When false, `get_` is not generated even if `syntax = "proto2"`
    pub generate_getter: Option<bool>,
    /// Use `bytes::Bytes` for `bytes` fields
    pub carllerche_bytes_for_bytes: Option<bool>,
    /// Use `bytes::Bytes` for `string` fields
    pub carllerche_bytes_for_string: Option<bool>,
    /// Use `std::Vec` to store repeated messages fields
    pub repeated_field_vec: Option<bool>,
    /// Implement serde_derive for messages
    pub serde_derive: Option<bool>,
    /// Make sure `Customize` is always used with `..Default::default()`
    /// for future compatibility.
    _future_options: (),
}

impl Customize {
    /// Update fields of self with fields defined in other customize
    pub fn update_with(&mut self, that: &Customize) {
        if let Some(v) = that.expose_oneof {
            self.expose_oneof = Some(v);
        }
        if let Some(v) = that.expose_fields {
            self.expose_fields = Some(v);
        }
        if let Some(v) = that.generate_accessors {
            self.generate_accessors = Some(v);
        }
        if let Some(v) = that.generate_getter {
            self.generate_getter = Some(v);
        }
        if let Some(v) = that.carllerche_bytes_for_bytes {
            self.carllerche_bytes_for_bytes = Some(v);
        }
        if let Some(v) = that.carllerche_bytes_for_string {
            self.carllerche_bytes_for_string = Some(v);
        }
        if let Some(v) = that.repeated_field_vec {
            self.repeated_field_vec = Some(v);
        }
        if let Some(v) = that.serde_derive {
            self.serde_derive = Some(v);
        }
    }

    /// Update unset fields of self with fields from other customize
    pub fn set_defaults_from(&mut self, other: &Customize) {
        let mut tmp = other.clone();
        tmp.update_with(self);
        *self = tmp;
    }
}

pub fn customize_from_rustproto_for_message(source: &MessageOptions) -> Customize {
    let expose_oneof = rustproto::exts::expose_oneof.get(source);
    let expose_fields = rustproto::exts::expose_fields.get(source);
    let generate_accessors = rustproto::exts::generate_accessors.get(source);
    let generate_getter = rustproto::exts::generate_getter.get(source);
    let carllerche_bytes_for_bytes = rustproto::exts::carllerche_bytes_for_bytes.get(source);
    let carllerche_bytes_for_string = rustproto::exts::carllerche_bytes_for_string.get(source);
    let repeated_field_vec = rustproto::exts::repeated_field_vec.get(source);
    let serde_derive = rustproto::exts::serde_derive.get(source);
    Customize {
        expose_oneof,
        expose_fields,
        generate_accessors,
        generate_getter,
        carllerche_bytes_for_bytes,
        carllerche_bytes_for_string,
        repeated_field_vec,
        serde_derive,
        _future_options: (),
    }
}

pub fn customize_from_rustproto_for_field(source: &FieldOptions) -> Customize {
    let expose_oneof = None;
    let expose_fields = rustproto::exts::expose_fields_field.get(source);
    let generate_accessors = rustproto::exts::generate_accessors_field.get(source);
    let generate_getter = rustproto::exts::generate_getter_field.get(source);
    let carllerche_bytes_for_bytes = rustproto::exts::carllerche_bytes_for_bytes_field.get(source);
    let carllerche_bytes_for_string = rustproto::exts::carllerche_bytes_for_string_field.get(source);
    let repeated_field_vec = rustproto::exts::repeated_field_vec_field.get(source);
    let serde_derive = None;
    Customize {
        expose_oneof,
        expose_fields,
        generate_accessors,
        generate_getter,
        carllerche_bytes_for_bytes,
        carllerche_bytes_for_string,
        repeated_field_vec,
        serde_derive,
        _future_options: (),
    }
}

pub fn customize_from_rustproto_for_file(source: &FileOptions) -> Customize {
    let expose_oneof = rustproto::exts::expose_oneof_all.get(source);
    let expose_fields = rustproto::exts::expose_fields_all.get(source);
    let generate_accessors = rustproto::exts::generate_accessors_all.get(source);
    let generate_getter = rustproto::exts::generate_getter_all.get(source);
    let carllerche_bytes_for_bytes = rustproto::exts::carllerche_bytes_for_bytes_all.get(source);
    let carllerche_bytes_for_string = rustproto::exts::carllerche_bytes_for_string_all.get(source);
    let repeated_field_vec = rustproto::exts::repeated_field_vec_all.get(source);
    let serde_derive = rustproto::exts::serde_derive_all.get(source);
    Customize {
        expose_oneof,
        expose_fields,
        generate_accessors,
        generate_getter,
        carllerche_bytes_for_bytes,
        carllerche_bytes_for_string,
        repeated_field_vec,
        serde_derive,
        _future_options: (),
    }
}
<commit_msg>Customize::_future_options must be public<commit_after>use protobuf::rustproto;
use protobuf::descriptor::FieldOptions;
use protobuf::descriptor::MessageOptions;
use protobuf::descriptor::FileOptions;

/// Specifies style of generated code.
/// Generated files can be customized using this proto
/// or using `rustproto.proto` options.
#[derive(Default, Debug, Clone)]
pub struct Customize {
    /// Make oneof enum public.
    pub expose_oneof: Option<bool>,
    /// When true all fields are public, and accessors are not generated
    pub expose_fields: Option<bool>,
    /// When false, `get_`, `set_`, `mut_` etc. accessors are not generated
    pub generate_accessors: Option<bool>,
    /// When false, `get_` is not generated even if `syntax = "proto2"`
    pub generate_getter: Option<bool>,
    /// Use `bytes::Bytes` for `bytes` fields
    pub carllerche_bytes_for_bytes: Option<bool>,
    /// Use `bytes::Bytes` for `string` fields
    pub carllerche_bytes_for_string: Option<bool>,
    /// Use `std::Vec` to store repeated messages fields
    pub repeated_field_vec: Option<bool>,
    /// Implement serde_derive for messages
    pub serde_derive: Option<bool>,
    /// Make sure `Customize` is always used with `..Default::default()`
    /// for future compatibility.
    pub _future_options: (),
}

impl Customize {
    /// Update fields of self with fields defined in other customize
    pub fn update_with(&mut self, that: &Customize) {
        if let Some(v) = that.expose_oneof {
            self.expose_oneof = Some(v);
        }
        if let Some(v) = that.expose_fields {
            self.expose_fields = Some(v);
        }
        if let Some(v) = that.generate_accessors {
            self.generate_accessors = Some(v);
        }
        if let Some(v) = that.generate_getter {
            self.generate_getter = Some(v);
        }
        if let Some(v) = that.carllerche_bytes_for_bytes {
            self.carllerche_bytes_for_bytes = Some(v);
        }
        if let Some(v) = that.carllerche_bytes_for_string {
            self.carllerche_bytes_for_string = Some(v);
        }
        if let Some(v) = that.repeated_field_vec {
            self.repeated_field_vec = Some(v);
        }
        if let Some(v) = that.serde_derive {
            self.serde_derive = Some(v);
        }
    }

    /// Update unset fields of self with fields from other customize
    pub fn set_defaults_from(&mut self, other: &Customize) {
        let mut tmp = other.clone();
        tmp.update_with(self);
        *self = tmp;
    }
}

pub fn customize_from_rustproto_for_message(source: &MessageOptions) -> Customize {
    let expose_oneof = rustproto::exts::expose_oneof.get(source);
    let expose_fields = rustproto::exts::expose_fields.get(source);
    let generate_accessors = rustproto::exts::generate_accessors.get(source);
    let generate_getter = rustproto::exts::generate_getter.get(source);
    let carllerche_bytes_for_bytes = rustproto::exts::carllerche_bytes_for_bytes.get(source);
    let carllerche_bytes_for_string = rustproto::exts::carllerche_bytes_for_string.get(source);
    let repeated_field_vec = rustproto::exts::repeated_field_vec.get(source);
    let serde_derive = rustproto::exts::serde_derive.get(source);
    Customize {
        expose_oneof,
        expose_fields,
        generate_accessors,
        generate_getter,
        carllerche_bytes_for_bytes,
        carllerche_bytes_for_string,
        repeated_field_vec,
        serde_derive,
        _future_options: (),
    }
}

pub fn customize_from_rustproto_for_field(source: &FieldOptions) -> Customize {
    let expose_oneof = None;
    let expose_fields = rustproto::exts::expose_fields_field.get(source);
    let generate_accessors = rustproto::exts::generate_accessors_field.get(source);
    let generate_getter = rustproto::exts::generate_getter_field.get(source);
    let carllerche_bytes_for_bytes = rustproto::exts::carllerche_bytes_for_bytes_field.get(source);
    let carllerche_bytes_for_string = rustproto::exts::carllerche_bytes_for_string_field.get(source);
    let repeated_field_vec = rustproto::exts::repeated_field_vec_field.get(source);
    let serde_derive = None;
    Customize {
        expose_oneof,
        expose_fields,
        generate_accessors,
        generate_getter,
        carllerche_bytes_for_bytes,
        carllerche_bytes_for_string,
        repeated_field_vec,
        serde_derive,
        _future_options: (),
    }
}

pub fn customize_from_rustproto_for_file(source: &FileOptions) -> Customize {
    let expose_oneof = rustproto::exts::expose_oneof_all.get(source);
    let expose_fields = rustproto::exts::expose_fields_all.get(source);
    let generate_accessors = rustproto::exts::generate_accessors_all.get(source);
    let generate_getter = rustproto::exts::generate_getter_all.get(source);
    let carllerche_bytes_for_bytes = rustproto::exts::carllerche_bytes_for_bytes_all.get(source);
    let carllerche_bytes_for_string = rustproto::exts::carllerche_bytes_for_string_all.get(source);
    let repeated_field_vec = rustproto::exts::repeated_field_vec_all.get(source);
    let serde_derive = rustproto::exts::serde_derive_all.get(source);
    Customize {
        expose_oneof,
        expose_fields,
        generate_accessors,
        generate_getter,
        carllerche_bytes_for_bytes,
        carllerche_bytes_for_string,
        repeated_field_vec,
        serde_derive,
        _future_options: (),
    }
}
<|endoftext|>


<commit_before>use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::higher;
use clippy_utils::method_chain_args;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, PatKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;

declare_clippy_lint! {
    /// ### What it does
    /// Checks for unnecessary `ok()` in `while let`.
    ///
    /// ### Why is this bad?
    /// Calling `ok()` in `while let` is unnecessary, instead match
    /// on `Ok(pat)`
    ///
    /// ### Example
    /// ```ignore
    /// while let Some(value) = iter.next().ok() {
    ///     vec.push(value)
    /// }
    ///
    /// if let Some(valie) = iter.next().ok() {
    ///     vec.push(value)
    /// }
    /// ```
    /// Use instead:
    /// ```ignore
    /// while let Ok(value) = iter.next() {
    ///     vec.push(value)
    /// }
    ///
    /// if let Ok(value) = iter.next() {
    ///        vec.push_value)
    /// }
    /// ```
    pub MATCH_RESULT_OK,
    style,
    "usage of `ok()` in `let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead"
}

declare_lint_pass!(MatchResultOk => [MATCH_RESULT_OK]);

impl<'tcx> LateLintPass<'tcx> for MatchResultOk {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        if_chain! {
            if let Some(higher::IfLet { let_pat, let_expr, .. }) = higher::IfLet::hir(cx, expr);
            if let ExprKind::MethodCall(_, ok_span, [ref result_types_0, ..], _) = let_expr.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
            if let PatKind::TupleStruct(QPath::Resolved(_, x), y, _)  = let_pat.kind; //get operation
            if method_chain_args(let_expr, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized;
            if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(result_types_0), sym::result_type);
            if rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(x, false)) == "Some";

            then {

                let mut applicability = Applicability::MachineApplicable;
                let some_expr_string = snippet_with_applicability(cx, y[0].span, "", &mut applicability);
                let trimmed_ok = snippet_with_applicability(cx, let_expr.span.until(ok_span), "", &mut applicability);
                let sugg = format!(
                    "if let Ok({}) = {}",
                    some_expr_string,
                    trimmed_ok.trim().trim_end_matches('.'),
                );
                span_lint_and_sugg(
                    cx,
                    MATCH_RESULT_OK,
                    expr.span.with_hi(let_expr.span.hi()),
                    "matching on `Some` with `ok()` is redundant",
                    &format!("consider matching on `Ok({})` and removing the call to `ok` instead", some_expr_string),
                    sugg,
                    applicability,
                );
            }
        }

        if_chain! {
            if let Some(higher::WhileLet { let_pat, let_expr, .. }) = higher::WhileLet::hir(expr);
            if let ExprKind::MethodCall(_, ok_span, [ref result_types_0, ..], _) = let_expr.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
            if let PatKind::TupleStruct(QPath::Resolved(_, x), y, _)  = let_pat.kind; //get operation
            if method_chain_args(let_expr, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized;
            if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(result_types_0), sym::result_type);
            if rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(x, false)) == "Some";

            then {

                let mut applicability = Applicability::MachineApplicable;
                let some_expr_string = snippet_with_applicability(cx, y[0].span, "", &mut applicability);
                let trimmed_ok = snippet_with_applicability(cx, let_expr.span.until(ok_span), "", &mut applicability);
                let sugg = format!(
                    "while let Ok({}) = {}",
                    some_expr_string,
                    trimmed_ok.trim().trim_end_matches('.'),
                );
                span_lint_and_sugg(
                    cx,
                    MATCH_RESULT_OK,
                    expr.span.with_hi(let_expr.span.hi()),
                    "matching on `Some` with `ok()` is redundant",
                    &format!("consider matching on `Ok({})` and removing the call to `ok` instead", some_expr_string),
                    sugg,
                    applicability,
                );
            }
        }
    }
}
<commit_msg>Use a single if_chain<commit_after>use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::higher;
use clippy_utils::method_chain_args;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, PatKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;

declare_clippy_lint! {
    /// ### What it does
    /// Checks for unnecessary `ok()` in `while let`.
    ///
    /// ### Why is this bad?
    /// Calling `ok()` in `while let` is unnecessary, instead match
    /// on `Ok(pat)`
    ///
    /// ### Example
    /// ```ignore
    /// while let Some(value) = iter.next().ok() {
    ///     vec.push(value)
    /// }
    ///
    /// if let Some(valie) = iter.next().ok() {
    ///     vec.push(value)
    /// }
    /// ```
    /// Use instead:
    /// ```ignore
    /// while let Ok(value) = iter.next() {
    ///     vec.push(value)
    /// }
    ///
    /// if let Ok(value) = iter.next() {
    ///        vec.push_value)
    /// }
    /// ```
    pub MATCH_RESULT_OK,
    style,
    "usage of `ok()` in `let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead"
}

declare_lint_pass!(MatchResultOk => [MATCH_RESULT_OK]);

impl<'tcx> LateLintPass<'tcx> for MatchResultOk {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        let (let_pat, let_expr, ifwhile) = if let Some(higher::IfLet { let_pat, let_expr, .. }) = higher::IfLet::hir(cx, expr) {
            (let_pat, let_expr, "if")
        } else if let Some(higher::WhileLet { let_pat, let_expr, .. }) = higher::WhileLet::hir(expr) {
            (let_pat, let_expr, "while")
        } else {
            return
        };

        if_chain! {
            if let ExprKind::MethodCall(_, ok_span, [ref result_types_0, ..], _) = let_expr.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
            if let PatKind::TupleStruct(QPath::Resolved(_, x), y, _)  = let_pat.kind; //get operation
            if method_chain_args(let_expr, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized;
            if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(result_types_0), sym::result_type);
            if rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(x, false)) == "Some";

            then {

                let mut applicability = Applicability::MachineApplicable;
                let some_expr_string = snippet_with_applicability(cx, y[0].span, "", &mut applicability);
                let trimmed_ok = snippet_with_applicability(cx, let_expr.span.until(ok_span), "", &mut applicability);
                let sugg = format!(
                    "{} let Ok({}) = {}",
                    ifwhile,
                    some_expr_string,
                    trimmed_ok.trim().trim_end_matches('.'),
                );
                span_lint_and_sugg(
                    cx,
                    MATCH_RESULT_OK,
                    expr.span.with_hi(let_expr.span.hi()),
                    "matching on `Some` with `ok()` is redundant",
                    &format!("consider matching on `Ok({})` and removing the call to `ok` instead", some_expr_string),
                    sugg,
                    applicability,
                );
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate cell_gc;
#[macro_use]
extern crate cell_gc_derive;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate nom;
#[macro_use]
extern crate error_chain;

pub mod errors {
    error_chain!{}
}

pub mod value;

pub mod parse;
mod compile;
mod env;
pub mod vm;

mod builtins;
pub mod toplevel;
<commit_msg>lisp: Silence warning about unused doc comments in error-chain.<commit_after>extern crate cell_gc;
#[macro_use]
extern crate cell_gc_derive;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate nom;
#[macro_use]
extern crate error_chain;

#[allow(unused_doc_comment)] // silence new warning in Nightly
pub mod errors {
    error_chain!{}
}

pub mod value;

pub mod parse;
mod compile;
mod env;
pub mod vm;

mod builtins;
pub mod toplevel;
<|endoftext|>


<commit_before>fn main() {
    // Prevent building SPIRV-Cross on wasm32 target
    let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH");
    if let Ok(arch) = target_arch {
        if "wasm32" == arch {
            return;
        }
    }

    let target_vendor = std::env::var("CARGO_CFG_TARGET_VENDOR");
    let is_apple = target_vendor.is_ok() && target_vendor.unwrap() == "apple";

    let target_os = std::env::var("CARGO_CFG_TARGET_OS");
    let is_ios = target_os.is_ok() && target_os.unwrap() == "ios";

    let mut build = cc::Build::new();
    build.cpp(true);

    let compiler = build.try_get_compiler();
    let is_clang = compiler.is_ok() && compiler.unwrap().is_like_clang();

    if is_apple && (is_clang || is_ios) {
        build.flag("-std=c++14").cpp_set_stdlib("c++");
    } else {
        build.flag_if_supported("-std=c++14");
    }

    build
        .file("src/wrapper.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cfg.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cross.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cross_parsed_ir.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_parser.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cross_util.cpp");

    // Ideally the GLSL compiler would be omitted here, but the HLSL and MSL compiler
    // currently inherit from it. So it's necessary to unconditionally include it here.
    build
        .file("src/vendor/SPIRV-Cross/spirv_glsl.cpp")
        .flag("-DSPIRV_CROSS_WRAPPER_GLSL");

    #[cfg(feature = "hlsl")]
    build
        .file("src/vendor/SPIRV-Cross/spirv_hlsl.cpp")
        .flag("-DSPIRV_CROSS_WRAPPER_HLSL");

    #[cfg(feature = "msl")]
    build
        .file("src/vendor/SPIRV-Cross/spirv_msl.cpp")
        .flag("-DSPIRV_CROSS_WRAPPER_MSL");

    build.compile("spirv-cross-rust-wrapper");
}
<commit_msg>Disable exceptions<commit_after>fn main() {
    // Prevent building SPIRV-Cross on wasm32 target
    let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH");
    if let Ok(arch) = target_arch {
        if "wasm32" == arch {
            return;
        }
    }

    let target_vendor = std::env::var("CARGO_CFG_TARGET_VENDOR");
    let is_apple = target_vendor.is_ok() && target_vendor.unwrap() == "apple";

    let target_os = std::env::var("CARGO_CFG_TARGET_OS");
    let is_ios = target_os.is_ok() && target_os.unwrap() == "ios";

    let mut build = cc::Build::new();
    build.cpp(true);

    let compiler = build.try_get_compiler();
    let is_clang = compiler.is_ok() && compiler.unwrap().is_like_clang();

    if is_apple && (is_clang || is_ios) {
        build.flag("-std=c++14").cpp_set_stdlib("c++");
    } else {
        build.flag_if_supported("-std=c++14");
    }

    build
        .flag("-DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS")
        .flag("-DSPIRV_CROSS_WRAPPER_NO_EXCEPTIONS");

    build
        .file("src/wrapper.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cfg.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cross.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cross_parsed_ir.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_parser.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cross_util.cpp");

    // Ideally the GLSL compiler would be omitted here, but the HLSL and MSL compiler
    // currently inherit from it. So it's necessary to unconditionally include it here.
    build
        .file("src/vendor/SPIRV-Cross/spirv_glsl.cpp")
        .flag("-DSPIRV_CROSS_WRAPPER_GLSL");

    #[cfg(feature = "hlsl")]
    build
        .file("src/vendor/SPIRV-Cross/spirv_hlsl.cpp")
        .flag("-DSPIRV_CROSS_WRAPPER_HLSL");

    #[cfg(feature = "msl")]
    build
        .file("src/vendor/SPIRV-Cross/spirv_msl.cpp")
        .flag("-DSPIRV_CROSS_WRAPPER_MSL");

    build.compile("spirv-cross-rust-wrapper");
}
<|endoftext|>


<commit_before>use std::env;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};

fn template_dir() -> PathBuf {
    let mut path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
    path.push("templates");
    path
}

pub fn get_template_source(tpl_file: &str) -> String {
    let mut path = template_dir();
    path.push(Path::new(tpl_file));
    let mut f = match File::open(&path) {
        Err(_) => {
            let msg = format!("unable to open template file '{}'",
                              &path.to_str().unwrap());
            panic!(msg);
        },
        Ok(f) => f,
    };
    let mut s = String::new();
    f.read_to_string(&mut s).unwrap();
    s
}
<commit_msg>Add function to find template relative to another template's path<commit_after>use std::env;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};

fn template_dir() -> PathBuf {
    let mut path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
    path.push("templates");
    path
}

pub fn find_template_from_path<'a>(path: &str, start_at: Option<&str>) -> PathBuf {
    let root = template_dir();
    match start_at {
        Some(rel) => {
            let mut fs_rel_path = root.clone();
            fs_rel_path.push(rel);
            fs_rel_path = fs_rel_path.with_file_name(path);
            if fs_rel_path.exists() {
                return fs_rel_path.strip_prefix(&root).unwrap().to_owned();
            }
        },
        None => {},
    }

    let mut fs_abs_path = root.clone();
    let path = Path::new(path);
    fs_abs_path.push(Path::new(path));
    if fs_abs_path.exists() {
        path.to_owned()
    } else {
        panic!(format!("template '{:?}' not found", path.to_str()));
    }
}

pub fn get_template_source(tpl_file: &str) -> String {
    let mut path = template_dir();
    path.push(Path::new(tpl_file));
    let mut f = match File::open(&path) {
        Err(_) => {
            let msg = format!("unable to open template file '{}'",
                              &path.to_str().unwrap());
            panic!(msg);
        },
        Ok(f) => f,
    };
    let mut s = String::new();
    f.read_to_string(&mut s).unwrap();
    s
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;

use buffer::Buffer;
use command_buffer::cb::UnsafeCommandBuffer;
use command_buffer::pool::CommandPool;
use command_buffer::submit::SubmitAnyBuilder;
use command_buffer::submit::SubmitCommandBufferBuilder;
use device::Device;
use device::DeviceOwned;
use device::Queue;
use image::Image;
use sync::AccessFlagBits;
use sync::DummyFuture;
use sync::GpuFuture;
use sync::PipelineStages;
use SafeDeref;
use VulkanObject;

pub unsafe trait CommandBuffer: DeviceOwned {
    /// The command pool of the command buffer.
    type Pool: CommandPool;

    /// Returns the underlying `UnsafeCommandBuffer` of this command buffer.
    fn inner(&self) -> &UnsafeCommandBuffer<Self::Pool>;

    /// Checks whether this command buffer is allowed to be submitted after the `future` and on
    /// the given queue.
    ///
    /// **You should not call this function directly**, otherwise any further attempt to submit
    /// will return a runtime error.
    // TODO: better error
    fn submit_check(&self, future: &GpuFuture, queue: &Queue) -> Result<(), Box<error::Error>>;

    /// Executes this command buffer on a queue.
    ///
    /// > **Note**: This is just a shortcut for `execute_after`.
    ///
    /// # Panic
    ///
    /// Panics if the device of the command buffer is not the same as the device of the future.
    #[inline]
    fn execute(self, queue: Arc<Queue>) -> CommandBufferExecFuture<DummyFuture, Self>
        where Self: Sized + 'static
    {
        let device = queue.device().clone();
        self.execute_after(DummyFuture::new(device), queue)
    }

    /// Executes the command buffer after an existing future.
    ///
    /// This function requires the `'static` lifetime to be on the command buffer. This is because
    /// this function returns a `CommandBufferExecFuture` whose job is to lock resources and keep
    /// them alive while they are in use by the GPU. If `'static` wasn't required, you could call
    /// `std::mem::forget` on that object and "unlock" these resources. For more information about
    /// this problem, search the web for "rust thread scoped leakpocalypse".
    ///
    /// # Panic
    ///
    /// Panics if the device of the command buffer is not the same as the device of the future.
    #[inline]
    fn execute_after<F>(self, future: F, queue: Arc<Queue>) -> CommandBufferExecFuture<F, Self>
        where Self: Sized + 'static, F: GpuFuture
    {
        assert_eq!(self.device().internal_object(), future.device().internal_object());

        self.submit_check(&future, &queue).expect("Forbidden");     // TODO: error

        if !future.queue_change_allowed() {
            assert!(future.queue().unwrap().is_same(&queue));
        }

        CommandBufferExecFuture {
            previous: future,
            command_buffer: self,
            queue: queue,
            submitted: Mutex::new(false),
            finished: AtomicBool::new(false),
        }
    }

    fn check_buffer_access(&self, buffer: &Buffer, exclusive: bool, queue: &Queue)
                           -> Result<Option<(PipelineStages, AccessFlagBits)>, ()>;

    fn check_image_access(&self, image: &Image, exclusive: bool, queue: &Queue)
                          -> Result<Option<(PipelineStages, AccessFlagBits)>, ()>;

    // FIXME: lots of other methods
}

unsafe impl<T> CommandBuffer for T where T: SafeDeref, T::Target: CommandBuffer {
    type Pool = <T::Target as CommandBuffer>::Pool;

    #[inline]
    fn inner(&self) -> &UnsafeCommandBuffer<Self::Pool> {
        (**self).inner()
    }

    #[inline]
    fn submit_check(&self, future: &GpuFuture, queue: &Queue) -> Result<(), Box<error::Error>> {
        (**self).submit_check(future, queue)
    }

    #[inline]
    fn check_buffer_access(&self, buffer: &Buffer, exclusive: bool, queue: &Queue)
                           -> Result<Option<(PipelineStages, AccessFlagBits)>, ()>
    {
        (**self).check_buffer_access(buffer, exclusive, queue)
    }

    #[inline]
    fn check_image_access(&self, image: &Image, exclusive: bool, queue: &Queue)
                          -> Result<Option<(PipelineStages, AccessFlagBits)>, ()>
    {
        (**self).check_image_access(image, exclusive, queue)
    }
}

/// Represents a command buffer being executed by the GPU and the moment when the execution
/// finishes.
#[must_use = "Dropping this object will immediately block the thread until the GPU has finished processing the submission"]
pub struct CommandBufferExecFuture<F, Cb> where F: GpuFuture, Cb: CommandBuffer {
    previous: F,
    command_buffer: Cb,
    queue: Arc<Queue>,
    // True if the command buffer has already been submitted.
    // If flush is called multiple times, we want to block so that only one flushing is executed.
    // Therefore we use a `Mutex<bool>` and not an `AtomicBool`.
    submitted: Mutex<bool>,
    finished: AtomicBool,
}

unsafe impl<F, Cb> GpuFuture for CommandBufferExecFuture<F, Cb>
    where F: GpuFuture, Cb: CommandBuffer
{
    #[inline]
    fn cleanup_finished(&mut self) {
        self.previous.cleanup_finished();
    }

    unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, Box<error::Error>> {
        Ok(match try!(self.previous.build_submission()) {
            SubmitAnyBuilder::Empty => {
                let mut builder = SubmitCommandBufferBuilder::new();
                builder.add_command_buffer(self.command_buffer.inner());
                SubmitAnyBuilder::CommandBuffer(builder)
            },
            SubmitAnyBuilder::SemaphoresWait(sem) => {
                let mut builder: SubmitCommandBufferBuilder = sem.into();
                builder.add_command_buffer(self.command_buffer.inner());
                SubmitAnyBuilder::CommandBuffer(builder)
            },
            SubmitAnyBuilder::CommandBuffer(mut builder) => {
                // FIXME: add pipeline barrier
                builder.add_command_buffer(self.command_buffer.inner());
                SubmitAnyBuilder::CommandBuffer(builder)
            },
            SubmitAnyBuilder::QueuePresent(present) => {
                unimplemented!()        // TODO:
                /*present.submit();     // TODO: wrong
                let mut builder = SubmitCommandBufferBuilder::new();
                builder.add_command_buffer(self.command_buffer.inner());
                SubmitAnyBuilder::CommandBuffer(builder)*/
            },
        })
    }

    #[inline]
    fn flush(&self) -> Result<(), Box<error::Error>> {
        unsafe {
            let mut submitted = self.submitted.lock().unwrap();
            if *submitted {
                return Ok(());
            }

            let queue = self.queue.clone();

            match try!(self.build_submission()) {
                SubmitAnyBuilder::Empty => {},
                SubmitAnyBuilder::CommandBuffer(builder) => {
                    try!(builder.submit(&queue));
                },
                _ => unreachable!(),
            };

            // Only write `true` here in order to try again next time if we failed to submit.
            *submitted = true;
            Ok(())
        }
    }

    #[inline]
    unsafe fn signal_finished(&self) {
        self.finished.store(true, Ordering::SeqCst);
        self.previous.signal_finished();
    }

    #[inline]
    fn queue_change_allowed(&self) -> bool {
        false
    }

    #[inline]
    fn queue(&self) -> Option<&Arc<Queue>> {
        debug_assert!(match self.previous.queue() {
            None => true,
            Some(q) => q.is_same(&self.queue)
        });

        Some(&self.queue)
    }

    #[inline]
    fn check_buffer_access(&self, buffer: &Buffer, exclusive: bool, queue: &Queue)
                           -> Result<Option<(PipelineStages, AccessFlagBits)>, ()>
    {
        match self.command_buffer.check_buffer_access(buffer, exclusive, queue) {
            Ok(v) => Ok(v),
            Err(()) => self.previous.check_buffer_access(buffer, exclusive, queue),
        }
    }

    #[inline]
    fn check_image_access(&self, image: &Image, exclusive: bool, queue: &Queue)
                          -> Result<Option<(PipelineStages, AccessFlagBits)>, ()>
    {
        match self.command_buffer.check_image_access(image, exclusive, queue) {
            Ok(v) => Ok(v),
            Err(()) => self.previous.check_image_access(image, exclusive, queue),
        }
    }
}

unsafe impl<F, Cb> DeviceOwned for CommandBufferExecFuture<F, Cb>
    where F: GpuFuture, Cb: CommandBuffer
{
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.command_buffer.device()
    }
}

impl<F, Cb> Drop for CommandBufferExecFuture<F, Cb> where F: GpuFuture, Cb: CommandBuffer {
    fn drop(&mut self) {
        unsafe {
            if !*self.finished.get_mut() {
                // TODO: handle errors?
                self.flush().unwrap();
                // Block until the queue finished.
                self.queue.wait().unwrap();
                self.previous.signal_finished();
            }
        }
    }
}
<commit_msg>Remove spurious debug assert<commit_after>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;

use buffer::Buffer;
use command_buffer::cb::UnsafeCommandBuffer;
use command_buffer::pool::CommandPool;
use command_buffer::submit::SubmitAnyBuilder;
use command_buffer::submit::SubmitCommandBufferBuilder;
use device::Device;
use device::DeviceOwned;
use device::Queue;
use image::Image;
use sync::AccessFlagBits;
use sync::DummyFuture;
use sync::GpuFuture;
use sync::PipelineStages;
use SafeDeref;
use VulkanObject;

pub unsafe trait CommandBuffer: DeviceOwned {
    /// The command pool of the command buffer.
    type Pool: CommandPool;

    /// Returns the underlying `UnsafeCommandBuffer` of this command buffer.
    fn inner(&self) -> &UnsafeCommandBuffer<Self::Pool>;

    /// Checks whether this command buffer is allowed to be submitted after the `future` and on
    /// the given queue.
    ///
    /// **You should not call this function directly**, otherwise any further attempt to submit
    /// will return a runtime error.
    // TODO: better error
    fn submit_check(&self, future: &GpuFuture, queue: &Queue) -> Result<(), Box<error::Error>>;

    /// Executes this command buffer on a queue.
    ///
    /// > **Note**: This is just a shortcut for `execute_after`.
    ///
    /// # Panic
    ///
    /// Panics if the device of the command buffer is not the same as the device of the future.
    #[inline]
    fn execute(self, queue: Arc<Queue>) -> CommandBufferExecFuture<DummyFuture, Self>
        where Self: Sized + 'static
    {
        let device = queue.device().clone();
        self.execute_after(DummyFuture::new(device), queue)
    }

    /// Executes the command buffer after an existing future.
    ///
    /// This function requires the `'static` lifetime to be on the command buffer. This is because
    /// this function returns a `CommandBufferExecFuture` whose job is to lock resources and keep
    /// them alive while they are in use by the GPU. If `'static` wasn't required, you could call
    /// `std::mem::forget` on that object and "unlock" these resources. For more information about
    /// this problem, search the web for "rust thread scoped leakpocalypse".
    ///
    /// # Panic
    ///
    /// Panics if the device of the command buffer is not the same as the device of the future.
    #[inline]
    fn execute_after<F>(self, future: F, queue: Arc<Queue>) -> CommandBufferExecFuture<F, Self>
        where Self: Sized + 'static, F: GpuFuture
    {
        assert_eq!(self.device().internal_object(), future.device().internal_object());

        self.submit_check(&future, &queue).expect("Forbidden");     // TODO: error

        if !future.queue_change_allowed() {
            assert!(future.queue().unwrap().is_same(&queue));
        }

        CommandBufferExecFuture {
            previous: future,
            command_buffer: self,
            queue: queue,
            submitted: Mutex::new(false),
            finished: AtomicBool::new(false),
        }
    }

    fn check_buffer_access(&self, buffer: &Buffer, exclusive: bool, queue: &Queue)
                           -> Result<Option<(PipelineStages, AccessFlagBits)>, ()>;

    fn check_image_access(&self, image: &Image, exclusive: bool, queue: &Queue)
                          -> Result<Option<(PipelineStages, AccessFlagBits)>, ()>;

    // FIXME: lots of other methods
}

unsafe impl<T> CommandBuffer for T where T: SafeDeref, T::Target: CommandBuffer {
    type Pool = <T::Target as CommandBuffer>::Pool;

    #[inline]
    fn inner(&self) -> &UnsafeCommandBuffer<Self::Pool> {
        (**self).inner()
    }

    #[inline]
    fn submit_check(&self, future: &GpuFuture, queue: &Queue) -> Result<(), Box<error::Error>> {
        (**self).submit_check(future, queue)
    }

    #[inline]
    fn check_buffer_access(&self, buffer: &Buffer, exclusive: bool, queue: &Queue)
                           -> Result<Option<(PipelineStages, AccessFlagBits)>, ()>
    {
        (**self).check_buffer_access(buffer, exclusive, queue)
    }

    #[inline]
    fn check_image_access(&self, image: &Image, exclusive: bool, queue: &Queue)
                          -> Result<Option<(PipelineStages, AccessFlagBits)>, ()>
    {
        (**self).check_image_access(image, exclusive, queue)
    }
}

/// Represents a command buffer being executed by the GPU and the moment when the execution
/// finishes.
#[must_use = "Dropping this object will immediately block the thread until the GPU has finished processing the submission"]
pub struct CommandBufferExecFuture<F, Cb> where F: GpuFuture, Cb: CommandBuffer {
    previous: F,
    command_buffer: Cb,
    queue: Arc<Queue>,
    // True if the command buffer has already been submitted.
    // If flush is called multiple times, we want to block so that only one flushing is executed.
    // Therefore we use a `Mutex<bool>` and not an `AtomicBool`.
    submitted: Mutex<bool>,
    finished: AtomicBool,
}

unsafe impl<F, Cb> GpuFuture for CommandBufferExecFuture<F, Cb>
    where F: GpuFuture, Cb: CommandBuffer
{
    #[inline]
    fn cleanup_finished(&mut self) {
        self.previous.cleanup_finished();
    }

    unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, Box<error::Error>> {
        Ok(match try!(self.previous.build_submission()) {
            SubmitAnyBuilder::Empty => {
                let mut builder = SubmitCommandBufferBuilder::new();
                builder.add_command_buffer(self.command_buffer.inner());
                SubmitAnyBuilder::CommandBuffer(builder)
            },
            SubmitAnyBuilder::SemaphoresWait(sem) => {
                let mut builder: SubmitCommandBufferBuilder = sem.into();
                builder.add_command_buffer(self.command_buffer.inner());
                SubmitAnyBuilder::CommandBuffer(builder)
            },
            SubmitAnyBuilder::CommandBuffer(mut builder) => {
                // FIXME: add pipeline barrier
                builder.add_command_buffer(self.command_buffer.inner());
                SubmitAnyBuilder::CommandBuffer(builder)
            },
            SubmitAnyBuilder::QueuePresent(present) => {
                unimplemented!()        // TODO:
                /*present.submit();     // TODO: wrong
                let mut builder = SubmitCommandBufferBuilder::new();
                builder.add_command_buffer(self.command_buffer.inner());
                SubmitAnyBuilder::CommandBuffer(builder)*/
            },
        })
    }

    #[inline]
    fn flush(&self) -> Result<(), Box<error::Error>> {
        unsafe {
            let mut submitted = self.submitted.lock().unwrap();
            if *submitted {
                return Ok(());
            }

            let queue = self.queue.clone();

            match try!(self.build_submission()) {
                SubmitAnyBuilder::Empty => {},
                SubmitAnyBuilder::CommandBuffer(builder) => {
                    try!(builder.submit(&queue));
                },
                _ => unreachable!(),
            };

            // Only write `true` here in order to try again next time if we failed to submit.
            *submitted = true;
            Ok(())
        }
    }

    #[inline]
    unsafe fn signal_finished(&self) {
        self.finished.store(true, Ordering::SeqCst);
        self.previous.signal_finished();
    }

    #[inline]
    fn queue_change_allowed(&self) -> bool {
        false
    }

    #[inline]
    fn queue(&self) -> Option<&Arc<Queue>> {
        Some(&self.queue)
    }

    #[inline]
    fn check_buffer_access(&self, buffer: &Buffer, exclusive: bool, queue: &Queue)
                           -> Result<Option<(PipelineStages, AccessFlagBits)>, ()>
    {
        match self.command_buffer.check_buffer_access(buffer, exclusive, queue) {
            Ok(v) => Ok(v),
            Err(()) => self.previous.check_buffer_access(buffer, exclusive, queue),
        }
    }

    #[inline]
    fn check_image_access(&self, image: &Image, exclusive: bool, queue: &Queue)
                          -> Result<Option<(PipelineStages, AccessFlagBits)>, ()>
    {
        match self.command_buffer.check_image_access(image, exclusive, queue) {
            Ok(v) => Ok(v),
            Err(()) => self.previous.check_image_access(image, exclusive, queue),
        }
    }
}

unsafe impl<F, Cb> DeviceOwned for CommandBufferExecFuture<F, Cb>
    where F: GpuFuture, Cb: CommandBuffer
{
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.command_buffer.device()
    }
}

impl<F, Cb> Drop for CommandBufferExecFuture<F, Cb> where F: GpuFuture, Cb: CommandBuffer {
    fn drop(&mut self) {
        unsafe {
            if !*self.finished.get_mut() {
                // TODO: handle errors?
                self.flush().unwrap();
                // Block until the queue finished.
                self.queue.wait().unwrap();
                self.previous.signal_finished();
            }
        }
    }
}
<|endoftext|>


<commit_before>
extern crate time;
extern crate serial;
extern crate plugwise;

use std::io::prelude::*;
use plugwise::protocol::*;
use plugwise::stub;
use std::io;
use time::Duration;
use serial::prelude::*;
use std::rc::Rc;
use std::cell::RefCell;

struct PlugwiseInner<'a, I> {
    protocol: Rc<RefCell<Protocol<'a, I>>>
}

struct CircleInner<'a, I> {
    protocol: Rc<RefCell<Protocol<'a, I>>>,
    mac: u64
}

impl<'a, I: Read+Write+'a> PlugwiseInner<'a, I> {
    fn initialize(port: I) -> io::Result<PlugwiseInner<'a, I>> {
        let plugwise = PlugwiseInner {
            protocol: Rc::new(RefCell::new(Protocol::new(port)))
        };

        let result = try!(plugwise.protocol.borrow_mut().initialize());

        if !result.is_online {
            return Err(io::Error::new(io::ErrorKind::Other, "not online"));
        }

        Ok(plugwise)
    }
}

trait Plugwise<'a> {
    fn create_circle(&self, mac: u64) -> Box<Circle + 'a>;
    fn set_snoop(&self, snoop: ProtocolSnoop<'a>);
}

trait Circle {
    fn switch_on(&self) -> io::Result<()>;
    fn switch_off(&self) -> io::Result<()>;
}

impl<'a, I:Read+Write+'a> Plugwise<'a> for PlugwiseInner<'a, I> {
    fn create_circle(&self, mac: u64) -> Box<Circle+ 'a> {
        //Box::new(CircleInner::new(self.protocol.clone(), mac))
        Box::new(CircleInner {
            protocol: self.protocol.clone(),
            mac: mac
        })
    }

    fn set_snoop(&self, snoop: ProtocolSnoop<'a>) {
        self.protocol.borrow_mut().set_snoop(snoop);
    }
}

impl<'a, I:Read+Write+'a> Circle for CircleInner<'a, I> {
    fn switch_on(&self) -> io::Result<()> {
        try!(self.protocol.borrow_mut().switch(self.mac, true));
        Ok(())
    }

    fn switch_off(&self) -> io::Result<()> {
        try!(self.protocol.borrow_mut().switch(self.mac, false));
        Ok(())
    }
}

fn new_plugwise<'a>(device: &str) -> io::Result<Box<Plugwise<'a>+ 'a>> {
    let mut port = try!(serial::open(device));
    try!(port.configure(|settings| {
        settings.set_baud_rate(serial::Baud115200);
        settings.set_char_size(serial::Bits8);
        settings.set_parity(serial::ParityNone);
        settings.set_stop_bits(serial::Stop1);
    }));

    port.set_timeout(Duration::milliseconds(1000));
    let plugwise = try!(PlugwiseInner::initialize(port));

    Ok(Box::new(plugwise))
}

fn new_stub<'a>() -> io::Result<Box<Plugwise<'a>+ 'a>> {
    let port = stub::Stub::new();

    let plugwise = try!(PlugwiseInner::initialize(port));

    Ok(Box::new(plugwise))
}

fn main() {
    let mut debug = io::stdout();

    //let plugwise = new_plugwise("/dev/ttyUSB0").unwrap();
    let plugwise = new_stub().unwrap();
    plugwise.set_snoop(ProtocolSnoop::Debug(&mut debug));
    let circle = plugwise.create_circle(0x0123456789ABCDEF);
    circle.switch_on().unwrap();
    circle.switch_off().unwrap();
}
<commit_msg>renamed constructor functions<commit_after>
extern crate time;
extern crate serial;
extern crate plugwise;

use std::io::prelude::*;
use plugwise::protocol::*;
use plugwise::stub;
use std::io;
use time::Duration;
use serial::prelude::*;
use std::rc::Rc;
use std::cell::RefCell;

struct PlugwiseInner<'a, I> {
    protocol: Rc<RefCell<Protocol<'a, I>>>
}

struct CircleInner<'a, I> {
    protocol: Rc<RefCell<Protocol<'a, I>>>,
    mac: u64
}

impl<'a, I: Read+Write+'a> PlugwiseInner<'a, I> {
    fn initialize(port: I) -> io::Result<PlugwiseInner<'a, I>> {
        let plugwise = PlugwiseInner {
            protocol: Rc::new(RefCell::new(Protocol::new(port)))
        };

        let result = try!(plugwise.protocol.borrow_mut().initialize());

        if !result.is_online {
            return Err(io::Error::new(io::ErrorKind::Other, "not online"));
        }

        Ok(plugwise)
    }
}

trait Plugwise<'a> {
    fn create_circle(&self, mac: u64) -> Box<Circle + 'a>;
    fn set_snoop(&self, snoop: ProtocolSnoop<'a>);
}

trait Circle {
    fn switch_on(&self) -> io::Result<()>;
    fn switch_off(&self) -> io::Result<()>;
}

impl<'a, I:Read+Write+'a> Plugwise<'a> for PlugwiseInner<'a, I> {
    fn create_circle(&self, mac: u64) -> Box<Circle+ 'a> {
        //Box::new(CircleInner::new(self.protocol.clone(), mac))
        Box::new(CircleInner {
            protocol: self.protocol.clone(),
            mac: mac
        })
    }

    fn set_snoop(&self, snoop: ProtocolSnoop<'a>) {
        self.protocol.borrow_mut().set_snoop(snoop);
    }
}

impl<'a, I:Read+Write+'a> Circle for CircleInner<'a, I> {
    fn switch_on(&self) -> io::Result<()> {
        try!(self.protocol.borrow_mut().switch(self.mac, true));
        Ok(())
    }

    fn switch_off(&self) -> io::Result<()> {
        try!(self.protocol.borrow_mut().switch(self.mac, false));
        Ok(())
    }
}

fn plugwise_device<'a>(device: &str) -> io::Result<Box<Plugwise<'a>+ 'a>> {
    let mut port = try!(serial::open(device));
    try!(port.configure(|settings| {
        settings.set_baud_rate(serial::Baud115200);
        settings.set_char_size(serial::Bits8);
        settings.set_parity(serial::ParityNone);
        settings.set_stop_bits(serial::Stop1);
    }));

    port.set_timeout(Duration::milliseconds(1000));
    let plugwise = try!(PlugwiseInner::initialize(port));

    Ok(Box::new(plugwise))
}

fn plugwise_simulator<'a>() -> io::Result<Box<Plugwise<'a>+ 'a>> {
    let port = stub::Stub::new();

    let plugwise = try!(PlugwiseInner::initialize(port));

    Ok(Box::new(plugwise))
}

fn main() {
    let mut debug = io::stdout();

    //let plugwise = plugwise_device("/dev/ttyUSB0").unwrap();
    let plugwise = plugwise_simulator().unwrap();
    plugwise.set_snoop(ProtocolSnoop::Debug(&mut debug));
    let circle = plugwise.create_circle(0x0123456789ABCDEF);
    circle.switch_on().unwrap();
    circle.switch_off().unwrap();
}
<|endoftext|>


<commit_before>use super::{check, check_no_mismatches, check_types};

#[test]
fn block_expr_type_mismatch() {
    // FIXME fix double type mismatch
    check(
        r"
fn test() {
    let a: i32 = { 1i64 };
              // ^^^^^^^^ expected i32, got i64
                // ^^^^ expected i32, got i64
}
        ",
    );
}

#[test]
fn coerce_places() {
    check_no_mismatches(
        r#"
//- minicore: coerce_unsized
struct S<T> { a: T }

fn f<T>(_: &[T]) -> T { loop {} }
fn g<T>(_: S<&[T]>) -> T { loop {} }

fn gen<T>() -> *mut [T; 2] { loop {} }
fn test1<U>() -> *mut [U] {
    gen()
}

fn test2() {
    let arr: &[u8; 1] = &[1];

    let a: &[_] = arr;
    let b = f(arr);
    let c: &[_] = { arr };
    let d = g(S { a: arr });
    let e: [&[_]; 1] = [arr];
    let f: [&[_]; 2] = [arr; 2];
    let g: (&[_], &[_]) = (arr, arr);
}
"#,
    );
}

#[test]
fn let_stmt_coerce() {
    check(
        r"
//- minicore: coerce_unsized
fn test() {
    let x: &[isize] = &[1];
                   // ^^^^ adjustments: Deref(None), Borrow(Ref(Not)), Pointer(Unsize)
    let x: *const [isize] = &[1];
                         // ^^^^ adjustments: Deref(None), Borrow(RawPtr(Not)), Pointer(Unsize)
}
",
    );
}

#[test]
fn custom_coerce_unsized() {
    check(
        r#"
//- minicore: coerce_unsized
use core::{marker::Unsize, ops::CoerceUnsized};

struct A<T: ?Sized>(*const T);
struct B<T: ?Sized>(*const T);
struct C<T: ?Sized> { inner: *const T }

impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {}
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {}

fn foo1<T>(x: A<[T]>) -> A<[T]> { x }
fn foo2<T>(x: B<[T]>) -> B<[T]> { x }
fn foo3<T>(x: C<[T]>) -> C<[T]> { x }

fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) {
    let d = foo1(a);
              // ^ expected A<[{unknown}]>, got A<[u8; 2]>
    let e = foo2(b);
     // ^ type: B<[u8]>
    let f = foo3(c);
     // ^ type: C<[u8]>
}
"#,
    );
}

#[test]
fn if_coerce() {
    check_no_mismatches(
        r#"
//- minicore: coerce_unsized
fn foo<T>(x: &[T]) -> &[T] { x }
fn test() {
    let x = if true {
        foo(&[1])
         // ^^^^ adjustments: Deref(None), Borrow(Ref(Not)), Pointer(Unsize)
    } else {
        &[1]
    };
}
"#,
    );
}

#[test]
fn if_else_coerce() {
    check_no_mismatches(
        r#"
//- minicore: coerce_unsized
fn foo<T>(x: &[T]) -> &[T] { x }
fn test() {
    let x = if true {
        &[1]
    } else {
        foo(&[1])
    };
}
"#,
    )
}

#[test]
fn match_first_coerce() {
    check_no_mismatches(
        r#"
//- minicore: coerce_unsized
fn foo<T>(x: &[T]) -> &[T] { x }
fn test(i: i32) {
    let x = match i {
        2 => foo(&[2]),
              // ^^^^ adjustments: Deref(None), Borrow(Ref(Not)), Pointer(Unsize)
        1 => &[1],
        _ => &[3],
    };
}
"#,
    );
}

#[test]
fn match_second_coerce() {
    check_no_mismatches(
        r#"
//- minicore: coerce_unsized
fn foo<T>(x: &[T]) -> &[T] { loop {} }
                          // ^^^^^^^ adjustments: NeverToAny
fn test(i: i32) {
    let x = match i {
        1 => &[1],
        2 => foo(&[2]),
        _ => &[3],
    };
}
"#,
    );
}

#[test]
fn coerce_merge_one_by_one1() {
    cov_mark::check!(coerce_merge_fail_fallback);

    check(
        r"
fn test() {
    let t = &mut 1;
    let x = match 1 {
        1 => t as *mut i32,
        2 => t as &i32,
           //^^^^^^^^^ expected *mut i32, got &i32
        _ => t as *const i32,
          // ^^^^^^^^^^^^^^^ adjustments: Pointer(MutToConstPointer)

    };
    x;
  //^ type: *const i32

}
        ",
    );
}

#[test]
fn return_coerce_unknown() {
    check_types(
        r"
fn foo() -> u32 {
    return unknown;
         //^^^^^^^ u32
}
        ",
    );
}

#[test]
fn coerce_autoderef() {
    check_no_mismatches(
        r"
struct Foo;
fn takes_ref_foo(x: &Foo) {}
fn test() {
    takes_ref_foo(&Foo);
    takes_ref_foo(&&Foo);
    takes_ref_foo(&&&Foo);
}",
    );
}

#[test]
fn coerce_autoderef_generic() {
    check_no_mismatches(
        r#"
struct Foo;
fn takes_ref<T>(x: &T) -> T { *x }
fn test() {
    takes_ref(&Foo);
    takes_ref(&&Foo);
    takes_ref(&&&Foo);
}
"#,
    );
}

#[test]
fn coerce_autoderef_block() {
    check_no_mismatches(
        r#"
//- minicore: deref
struct String {}
impl core::ops::Deref for String { type Target = str; }
fn takes_ref_str(x: &str) {}
fn returns_string() -> String { loop {} }
fn test() {
    takes_ref_str(&{ returns_string() });
               // ^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(None), Deref(Some(OverloadedDeref(Not))), Borrow(Ref(Not))
}
"#,
    );
}

#[test]
fn closure_return_coerce() {
    check_no_mismatches(
        r"
fn foo() {
    let x = || {
        if true {
            return &1u32;
        }
        &&1u32
    };
}",
    );
}

#[test]
fn coerce_fn_item_to_fn_ptr() {
    check_no_mismatches(
        r"
fn foo(x: u32) -> isize { 1 }
fn test() {
    let f: fn(u32) -> isize = foo;
                           // ^^^ adjustments: Pointer(ReifyFnPointer)
    let f: unsafe fn(u32) -> isize = foo;
                                  // ^^^ adjustments: Pointer(ReifyFnPointer)
}",
    );
}

#[test]
fn coerce_fn_items_in_match_arms() {
    cov_mark::check!(coerce_fn_reification);

    check_types(
        r"
fn foo1(x: u32) -> isize { 1 }
fn foo2(x: u32) -> isize { 2 }
fn foo3(x: u32) -> isize { 3 }
fn test() {
    let x = match 1 {
        1 => foo1,
        2 => foo2,
        _ => foo3,
    };
    x;
  //^ fn(u32) -> isize
}",
    );
}

#[test]
fn coerce_closure_to_fn_ptr() {
    check_no_mismatches(
        r"
fn test() {
    let f: fn(u32) -> isize = |x| { 1 };
}",
    );
}

#[test]
fn coerce_placeholder_ref() {
    // placeholders should unify, even behind references
    check_no_mismatches(
        r"
struct S<T> { t: T }
impl<TT> S<TT> {
    fn get(&self) -> &TT {
        &self.t
    }
}",
    );
}

#[test]
fn coerce_unsize_array() {
    check_types(
        r#"
//- minicore: coerce_unsized
fn test() {
    let f: &[usize] = &[1, 2, 3];
                      //^ usize
}"#,
    );
}

#[test]
fn coerce_unsize_trait_object_simple() {
    check_types(
        r#"
//- minicore: coerce_unsized
trait Foo<T, U> {}
trait Bar<U, T, X>: Foo<T, U> {}
trait Baz<T, X>: Bar<usize, T, X> {}

struct S<T, X>;
impl<T, X> Foo<T, usize> for S<T, X> {}
impl<T, X> Bar<usize, T, X> for S<T, X> {}
impl<T, X> Baz<T, X> for S<T, X> {}

fn test() {
    let obj: &dyn Baz<i8, i16> = &S;
                                //^ S<i8, i16>
    let obj: &dyn Bar<_, i8, i16> = &S;
                                   //^ S<i8, i16>
    let obj: &dyn Foo<i8, _> = &S;
                              //^ S<i8, {unknown}>
}"#,
    );
}

#[test]
fn coerce_unsize_super_trait_cycle() {
    check_no_mismatches(
        r#"
//- minicore: coerce_unsized
trait A {}
trait B: C + A {}
trait C: B {}
trait D: C

struct S;
impl A for S {}
impl B for S {}
impl C for S {}
impl D for S {}

fn test() {
    let obj: &dyn D = &S;
    let obj: &dyn A = &S;
}
"#,
    );
}

#[test]
fn coerce_unsize_generic() {
    // FIXME: fix the type mismatches here
    check(
        r#"
//- minicore: coerce_unsized
struct Foo<T> { t: T };
struct Bar<T>(Foo<T>);

fn test() {
    let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
                                   //^^^^^^^^^ expected [usize], got [usize; 3]
    let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
                         //^^^^^^^^^^^^^^^^^^^^^^^^^^ expected &Bar<[usize]>, got &Bar<[i32; 3]>
}
"#,
    );
}

#[test]
fn coerce_unsize_apit() {
    // FIXME: #8984
    check(
        r#"
//- minicore: coerce_unsized
trait Foo {}

fn test(f: impl Foo) {
    let _: &dyn Foo = &f;
                    //^^ expected &dyn Foo, got &impl Foo
}
        "#,
    );
}

#[test]
fn two_closures_lub() {
    check_types(
        r#"
fn foo(c: i32) {
    let add = |a: i32, b: i32| a + b;
    let sub = |a, b| a - b;
            //^^^^^^^^^^^^ |i32, i32| -> i32
    if c > 42 { add } else { sub };
  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fn(i32, i32) -> i32
}
        "#,
    )
}

#[test]
fn match_diverging_branch_1() {
    check_types(
        r#"
enum Result<T> { Ok(T), Err }
fn parse<T>() -> T { loop {} }

fn test() -> i32 {
    let a = match parse() {
        Ok(val) => val,
        Err => return 0,
    };
    a
  //^ i32
}
        "#,
    )
}

#[test]
fn match_diverging_branch_2() {
    // same as 1 except for order of branches
    check_types(
        r#"
enum Result<T> { Ok(T), Err }
fn parse<T>() -> T { loop {} }

fn test() -> i32 {
    let a = match parse() {
        Err => return 0,
        Ok(val) => val,
    };
    a
  //^ i32
}
        "#,
    )
}

#[test]
fn panic_macro() {
    check_no_mismatches(
        r#"
mod panic {
    #[macro_export]
    pub macro panic_2015 {
        () => (
            $crate::panicking::panic()
        ),
    }
}

mod panicking {
    pub fn panic() -> ! { loop {} }
}

#[rustc_builtin_macro = "core_panic"]
macro_rules! panic {
    // Expands to either `$crate::panic::panic_2015` or `$crate::panic::panic_2021`
    // depending on the edition of the caller.
    ($($arg:tt)*) => {
        /* compiler built-in */
    };
}

fn main() {
    panic!()
}
        "#,
    );
}

#[test]
fn coerce_unsize_expected_type() {
    check_no_mismatches(
        r#"
//- minicore: coerce_unsized
fn main() {
    let foo: &[u32] = &[1, 2];
    let foo: &[u32] = match true {
        true => &[1, 2],
        false => &[1, 2, 3],
    };
    let foo: &[u32] = if true {
        &[1, 2]
    } else {
        &[1, 2, 3]
    };
}
        "#,
    );
}

#[test]
fn coerce_array_elems_lub() {
    check_no_mismatches(
        r#"
fn f() {}
fn g() {}

fn test() {
    [f, g];
}
        "#,
    );
}
<commit_msg>Add test for #9560<commit_after>use super::{check, check_no_mismatches, check_types};

#[test]
fn block_expr_type_mismatch() {
    // FIXME fix double type mismatch
    check(
        r"
fn test() {
    let a: i32 = { 1i64 };
              // ^^^^^^^^ expected i32, got i64
                // ^^^^ expected i32, got i64
}
        ",
    );
}

#[test]
fn coerce_places() {
    check_no_mismatches(
        r#"
//- minicore: coerce_unsized
struct S<T> { a: T }

fn f<T>(_: &[T]) -> T { loop {} }
fn g<T>(_: S<&[T]>) -> T { loop {} }

fn gen<T>() -> *mut [T; 2] { loop {} }
fn test1<U>() -> *mut [U] {
    gen()
}

fn test2() {
    let arr: &[u8; 1] = &[1];

    let a: &[_] = arr;
    let b = f(arr);
    let c: &[_] = { arr };
    let d = g(S { a: arr });
    let e: [&[_]; 1] = [arr];
    let f: [&[_]; 2] = [arr; 2];
    let g: (&[_], &[_]) = (arr, arr);
}
"#,
    );
}

#[test]
fn let_stmt_coerce() {
    check(
        r"
//- minicore: coerce_unsized
fn test() {
    let x: &[isize] = &[1];
                   // ^^^^ adjustments: Deref(None), Borrow(Ref(Not)), Pointer(Unsize)
    let x: *const [isize] = &[1];
                         // ^^^^ adjustments: Deref(None), Borrow(RawPtr(Not)), Pointer(Unsize)
}
",
    );
}

#[test]
fn custom_coerce_unsized() {
    check(
        r#"
//- minicore: coerce_unsized
use core::{marker::Unsize, ops::CoerceUnsized};

struct A<T: ?Sized>(*const T);
struct B<T: ?Sized>(*const T);
struct C<T: ?Sized> { inner: *const T }

impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {}
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {}

fn foo1<T>(x: A<[T]>) -> A<[T]> { x }
fn foo2<T>(x: B<[T]>) -> B<[T]> { x }
fn foo3<T>(x: C<[T]>) -> C<[T]> { x }

fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) {
    let d = foo1(a);
              // ^ expected A<[{unknown}]>, got A<[u8; 2]>
    let e = foo2(b);
     // ^ type: B<[u8]>
    let f = foo3(c);
     // ^ type: C<[u8]>
}
"#,
    );
}

#[test]
fn if_coerce() {
    check_no_mismatches(
        r#"
//- minicore: coerce_unsized
fn foo<T>(x: &[T]) -> &[T] { x }
fn test() {
    let x = if true {
        foo(&[1])
         // ^^^^ adjustments: Deref(None), Borrow(Ref(Not)), Pointer(Unsize)
    } else {
        &[1]
    };
}
"#,
    );
}

#[test]
fn if_else_coerce() {
    check_no_mismatches(
        r#"
//- minicore: coerce_unsized
fn foo<T>(x: &[T]) -> &[T] { x }
fn test() {
    let x = if true {
        &[1]
    } else {
        foo(&[1])
    };
}
"#,
    )
}

#[test]
fn match_first_coerce() {
    check_no_mismatches(
        r#"
//- minicore: coerce_unsized
fn foo<T>(x: &[T]) -> &[T] { x }
fn test(i: i32) {
    let x = match i {
        2 => foo(&[2]),
              // ^^^^ adjustments: Deref(None), Borrow(Ref(Not)), Pointer(Unsize)
        1 => &[1],
        _ => &[3],
    };
}
"#,
    );
}

#[test]
fn match_second_coerce() {
    check_no_mismatches(
        r#"
//- minicore: coerce_unsized
fn foo<T>(x: &[T]) -> &[T] { loop {} }
                          // ^^^^^^^ adjustments: NeverToAny
fn test(i: i32) {
    let x = match i {
        1 => &[1],
        2 => foo(&[2]),
        _ => &[3],
    };
}
"#,
    );
}

#[test]
fn coerce_merge_one_by_one1() {
    cov_mark::check!(coerce_merge_fail_fallback);

    check(
        r"
fn test() {
    let t = &mut 1;
    let x = match 1 {
        1 => t as *mut i32,
        2 => t as &i32,
           //^^^^^^^^^ expected *mut i32, got &i32
        _ => t as *const i32,
          // ^^^^^^^^^^^^^^^ adjustments: Pointer(MutToConstPointer)

    };
    x;
  //^ type: *const i32

}
        ",
    );
}

#[test]
fn return_coerce_unknown() {
    check_types(
        r"
fn foo() -> u32 {
    return unknown;
         //^^^^^^^ u32
}
        ",
    );
}

#[test]
fn coerce_autoderef() {
    check_no_mismatches(
        r"
struct Foo;
fn takes_ref_foo(x: &Foo) {}
fn test() {
    takes_ref_foo(&Foo);
    takes_ref_foo(&&Foo);
    takes_ref_foo(&&&Foo);
}",
    );
}

#[test]
fn coerce_autoderef_generic() {
    check_no_mismatches(
        r#"
struct Foo;
fn takes_ref<T>(x: &T) -> T { *x }
fn test() {
    takes_ref(&Foo);
    takes_ref(&&Foo);
    takes_ref(&&&Foo);
}
"#,
    );
}

#[test]
fn coerce_autoderef_block() {
    check_no_mismatches(
        r#"
//- minicore: deref
struct String {}
impl core::ops::Deref for String { type Target = str; }
fn takes_ref_str(x: &str) {}
fn returns_string() -> String { loop {} }
fn test() {
    takes_ref_str(&{ returns_string() });
               // ^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(None), Deref(Some(OverloadedDeref(Not))), Borrow(Ref(Not))
}
"#,
    );
}

#[test]
fn closure_return_coerce() {
    check_no_mismatches(
        r"
fn foo() {
    let x = || {
        if true {
            return &1u32;
        }
        &&1u32
    };
}",
    );
}

#[test]
fn coerce_fn_item_to_fn_ptr() {
    check_no_mismatches(
        r"
fn foo(x: u32) -> isize { 1 }
fn test() {
    let f: fn(u32) -> isize = foo;
                           // ^^^ adjustments: Pointer(ReifyFnPointer)
    let f: unsafe fn(u32) -> isize = foo;
                                  // ^^^ adjustments: Pointer(ReifyFnPointer)
}",
    );
}

#[test]
fn coerce_fn_items_in_match_arms() {
    cov_mark::check!(coerce_fn_reification);

    check_types(
        r"
fn foo1(x: u32) -> isize { 1 }
fn foo2(x: u32) -> isize { 2 }
fn foo3(x: u32) -> isize { 3 }
fn test() {
    let x = match 1 {
        1 => foo1,
        2 => foo2,
        _ => foo3,
    };
    x;
  //^ fn(u32) -> isize
}",
    );
}

#[test]
fn coerce_closure_to_fn_ptr() {
    check_no_mismatches(
        r"
fn test() {
    let f: fn(u32) -> isize = |x| { 1 };
}",
    );
}

#[test]
fn coerce_placeholder_ref() {
    // placeholders should unify, even behind references
    check_no_mismatches(
        r"
struct S<T> { t: T }
impl<TT> S<TT> {
    fn get(&self) -> &TT {
        &self.t
    }
}",
    );
}

#[test]
fn coerce_unsize_array() {
    check_types(
        r#"
//- minicore: coerce_unsized
fn test() {
    let f: &[usize] = &[1, 2, 3];
                      //^ usize
}"#,
    );
}

#[test]
fn coerce_unsize_trait_object_simple() {
    check_types(
        r#"
//- minicore: coerce_unsized
trait Foo<T, U> {}
trait Bar<U, T, X>: Foo<T, U> {}
trait Baz<T, X>: Bar<usize, T, X> {}

struct S<T, X>;
impl<T, X> Foo<T, usize> for S<T, X> {}
impl<T, X> Bar<usize, T, X> for S<T, X> {}
impl<T, X> Baz<T, X> for S<T, X> {}

fn test() {
    let obj: &dyn Baz<i8, i16> = &S;
                                //^ S<i8, i16>
    let obj: &dyn Bar<_, i8, i16> = &S;
                                   //^ S<i8, i16>
    let obj: &dyn Foo<i8, _> = &S;
                              //^ S<i8, {unknown}>
}"#,
    );
}

#[test]
fn coerce_unsize_super_trait_cycle() {
    check_no_mismatches(
        r#"
//- minicore: coerce_unsized
trait A {}
trait B: C + A {}
trait C: B {}
trait D: C

struct S;
impl A for S {}
impl B for S {}
impl C for S {}
impl D for S {}

fn test() {
    let obj: &dyn D = &S;
    let obj: &dyn A = &S;
}
"#,
    );
}

#[test]
fn coerce_unsize_generic() {
    // FIXME: fix the type mismatches here
    check(
        r#"
//- minicore: coerce_unsized
struct Foo<T> { t: T };
struct Bar<T>(Foo<T>);

fn test() {
    let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
                                   //^^^^^^^^^ expected [usize], got [usize; 3]
    let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
                         //^^^^^^^^^^^^^^^^^^^^^^^^^^ expected &Bar<[usize]>, got &Bar<[i32; 3]>
}
"#,
    );
}

#[test]
fn coerce_unsize_apit() {
    // FIXME: #8984
    check(
        r#"
//- minicore: coerce_unsized
trait Foo {}

fn test(f: impl Foo) {
    let _: &dyn Foo = &f;
                    //^^ expected &dyn Foo, got &impl Foo
}
        "#,
    );
}

#[test]
fn two_closures_lub() {
    check_types(
        r#"
fn foo(c: i32) {
    let add = |a: i32, b: i32| a + b;
    let sub = |a, b| a - b;
            //^^^^^^^^^^^^ |i32, i32| -> i32
    if c > 42 { add } else { sub };
  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fn(i32, i32) -> i32
}
        "#,
    )
}

#[test]
fn match_diverging_branch_1() {
    check_types(
        r#"
enum Result<T> { Ok(T), Err }
fn parse<T>() -> T { loop {} }

fn test() -> i32 {
    let a = match parse() {
        Ok(val) => val,
        Err => return 0,
    };
    a
  //^ i32
}
        "#,
    )
}

#[test]
fn match_diverging_branch_2() {
    // same as 1 except for order of branches
    check_types(
        r#"
enum Result<T> { Ok(T), Err }
fn parse<T>() -> T { loop {} }

fn test() -> i32 {
    let a = match parse() {
        Err => return 0,
        Ok(val) => val,
    };
    a
  //^ i32
}
        "#,
    )
}

#[test]
fn panic_macro() {
    check_no_mismatches(
        r#"
mod panic {
    #[macro_export]
    pub macro panic_2015 {
        () => (
            $crate::panicking::panic()
        ),
    }
}

mod panicking {
    pub fn panic() -> ! { loop {} }
}

#[rustc_builtin_macro = "core_panic"]
macro_rules! panic {
    // Expands to either `$crate::panic::panic_2015` or `$crate::panic::panic_2021`
    // depending on the edition of the caller.
    ($($arg:tt)*) => {
        /* compiler built-in */
    };
}

fn main() {
    panic!()
}
        "#,
    );
}

#[test]
fn coerce_unsize_expected_type_1() {
    check_no_mismatches(
        r#"
//- minicore: coerce_unsized
fn main() {
    let foo: &[u32] = &[1, 2];
    let foo: &[u32] = match true {
        true => &[1, 2],
        false => &[1, 2, 3],
    };
    let foo: &[u32] = if true {
        &[1, 2]
    } else {
        &[1, 2, 3]
    };
}
        "#,
    );
}

#[test]
fn coerce_unsize_expected_type_2() {
    // FIXME: this is wrong, #9560
    check(
        r#"
//- minicore: coerce_unsized
struct InFile<T>;
impl<T> InFile<T> {
    fn with_value<U>(self, value: U) -> InFile<U> { InFile }
}
struct RecordField;
trait AstNode {}
impl AstNode for RecordField {}

fn takes_dyn(it: InFile<&dyn AstNode>) {}

fn test() {
    let x: InFile<()> = InFile;
    let n = &RecordField;
    takes_dyn(x.with_value(n));
           // ^^^^^^^^^^^^^^^ expected InFile<&dyn AstNode>, got InFile<&RecordField>
}
        "#,
    );
}

#[test]
fn coerce_array_elems_lub() {
    check_no_mismatches(
        r#"
fn f() {}
fn g() {}

fn test() {
    [f, g];
}
        "#,
    );
}
<|endoftext|>