<commit_before>export Font, create_test_font, test_font_bin;

import glyph::GlyphIndex;
import vec_to_ptr = vec::unsafe::to_ptr;
import libc::{ c_int, c_double, c_ulong };
import ptr::{ null, addr_of };
import azure::cairo::{
    cairo_font_face_t,
    cairo_scaled_font_t,
    cairo_glyph_t,
    cairo_text_extents_t,
    CAIRO_STATUS_SUCCESS,
};
import azure::cairo::bindgen::{
    cairo_font_face_destroy,
    cairo_scaled_font_destroy,
    cairo_scaled_font_status,
    cairo_scaled_font_text_to_glyphs,
    cairo_scaled_font_glyph_extents,
    cairo_glyph_free,
    cairo_status_to_string
};

#[doc = "
A font handle. Layout can use this to calculate glyph metrics
and the renderer can use it to render text.
"]
#[warn(no_non_implicitly_copyable_typarams)]
class Font/& {
    let fontbuf: [u8];
    let cairo_font: *cairo_scaled_font_t;
    let font_dtor: fn@();

    new(-fontbuf: [u8]) {

        let (cairo_font, font_dtor) = get_cairo_font(&copy fontbuf);
        assert cairo_font.is_not_null();

        self.fontbuf <- fontbuf;
        self.cairo_font = cairo_font;
        self.font_dtor = font_dtor;
    }

    drop {
        self.font_dtor();
    }

    fn buf() -> &self.[u8] {
        &self.fontbuf
    }

    fn glyph_idx(codepoint: char) -> option<GlyphIndex> {
        #debug("getting glyph for codepoint %u", codepoint as uint);
        let codepoint_str = str::from_char(codepoint);

        let mut glyphs: *cairo_glyph_t = null();
        let mut num_glyphs = 0 as c_int;

        let status = str::as_c_str(codepoint_str) { |codepoint_buf|
            cairo_scaled_font_text_to_glyphs(
                self.cairo_font,
                0.0 as c_double, 0.0 as c_double,
                codepoint_buf, codepoint_str.len() as c_int,
                addr_of(glyphs), addr_of(num_glyphs),
                null(), null(), null()
            )
        };

        ret if status == CAIRO_STATUS_SUCCESS {

            // This might not be true, but at least we'll know if it isn't
            assert num_glyphs == 1 as c_int;

            let glyph_index = unsafe { *glyphs }.index as GlyphIndex;
            #debug("glyph index is %?", glyph_index);
            cairo_glyph_free(glyphs);
            some(glyph_index)
        } else {
            #error("cairo did not give me a glyph for %u", codepoint as uint);
            none
        }
    }

    fn glyph_h_advance(glyph: GlyphIndex) -> int {

        #debug("getting h advance for glyph %?", glyph);

        let glyphs: [cairo_glyph_t] = [{
            index: glyph as c_ulong,
            x: 0 as c_double,
            y: 0 as c_double,
        }];
        let extents: cairo_text_extents_t = {
            x_bearing: 0 as c_double,
            y_bearing: 0 as c_double,
            width: 0 as c_double,
            height: 0 as c_double,
            x_advance: 0 as c_double,
            y_advance: 0 as c_double,
        };

        assert self.cairo_font.is_not_null();

        cairo_scaled_font_glyph_extents(
            self.cairo_font, unsafe { vec_to_ptr(glyphs) },
            1 as c_int, addr_of(extents));

        alt cairo_scaled_font_status(self.cairo_font) {
          status if status == CAIRO_STATUS_SUCCESS {

            #debug("x_advance: %?", extents.x_advance);
            #debug("y_advance: %?", extents.y_advance);

            ret extents.x_advance as int;
          }
         status {
            import str::unsafe::from_c_str;

            let status_cstr = cairo_status_to_string(status);
            let status_str = unsafe { from_c_str(status_cstr) };

            #error("cairo_scaled_font_glyph_extents status: %s", status_str);
            fail "failed to get glyph extents from cairo"
          }
        }
    }
}

fn get_cairo_font(buf: &[u8]) -> (*cairo_scaled_font_t, fn@()) {

    import libc::c_double;
    import azure::cairo;
    import cairo::{ cairo_matrix_t };
    import cairo::bindgen::{
        cairo_matrix_init_identity,
        cairo_matrix_scale,
        cairo_font_options_create,
        cairo_font_options_destroy,
        cairo_scaled_font_create,
        cairo_scaled_font_destroy
    };

    import cairo::bindgen::cairo_scaled_font_create;

    let mut (face, dtor) = get_cairo_face(buf);

    let idmatrix: cairo_matrix_t = {
        xx: 0 as c_double,
        yx: 0 as c_double,
        xy: 0 as c_double,
        yy: 0 as c_double,
        x0: 0 as c_double,
        y0: 0 as c_double
    };
    cairo_matrix_init_identity(addr_of(idmatrix));

    let fontmatrix = idmatrix;
    cairo_matrix_scale(addr_of(fontmatrix),
                       20f as c_double, 20f as c_double);

    let options = cairo_font_options_create();
    let cfont = cairo_scaled_font_create(face, addr_of(fontmatrix),
                                         addr_of(idmatrix), options);
    cairo_font_options_destroy(options);

    // FIXME: Need negative tests
    if cfont.is_null() {
        dtor();
        fail "unable to create cairo scaled font";
    }
    dtor = fn@(move dtor) { cairo_scaled_font_destroy(cfont); dtor() };

    (cfont, dtor)
}

#[cfg(target_os = "linux")]
fn get_cairo_face(buf: &[u8]) -> (*cairo_font_face_t, fn@()) {
    import freetype = azure::freetype;
    import freetype::{ FT_Error, FT_Library, FT_Face, FT_Long };
    import freetype::bindgen::{
        FT_Init_FreeType,
        FT_Done_FreeType,
        FT_New_Memory_Face,
        FT_Done_Face
    };
    import azure::cairo_ft;
    import cairo_ft::bindgen::cairo_ft_font_face_create_for_ft_face;

    impl methods for FT_Error {
        fn for_sure() { assert !self.failed() }
        fn failed() -> bool { self != 0 as FT_Error }
    }

    let mut dtor = fn@() { };

    let library: FT_Library = null();
    // FIXME: Need tests for failure case
    FT_Init_FreeType(addr_of(library)).for_sure();
    dtor = fn@(move dtor) { FT_Done_FreeType(library).for_sure(); dtor() };

    let face: FT_Face = null();
    vec::as_buf(*buf) { |cbuf|
        if FT_New_Memory_Face(library, cbuf, (*buf).len() as FT_Long,
                              0 as FT_Long, addr_of(face)).failed() {
            dtor();
            fail "unable to create FreeType face";
        }
    }
    dtor = fn@(move dtor) { FT_Done_Face(face).for_sure(); dtor() };

    let cface = cairo_ft_font_face_create_for_ft_face(face, 0 as c_int);
    if cface.is_null() {
        // FIXME: Need tests for failure case
        dtor();
        fail "unable to create cairo font face";
    }
    dtor = fn@(move dtor) { cairo_font_face_destroy(cface); dtor() };

    (cface, dtor)
}

#[cfg(target_os = "macos")]
mod cocoa {
    use cocoa;
    export cocoa;
}

#[cfg(target_os = "macos")]
fn get_cairo_face(buf: &[u8]) -> (*cairo_font_face_t, fn@()) {
    import unsafe::reinterpret_cast;
    import libc::size_t;
    import cocoa::cocoa;
    import cocoa::cg::cg::{
        CGDataProviderCreateWithData,
        CGDataProviderRelease,
        CGFontCreateWithDataProvider,
        CGFontRelease
    };
    import azure::cairo_quartz::bindgen::cairo_quartz_font_face_create_for_cgfont;

    let mut dtor = fn@() { };

    let fontprov = vec::as_buf(*buf) { |cbuf|
        CGDataProviderCreateWithData(
            null(),
            unsafe { reinterpret_cast(cbuf) },
            (*buf).len() as size_t,
            null()
        )
    };
    dtor = fn@(move dtor) { CGDataProviderRelease(fontprov); dtor() };

    let cgfont = CGFontCreateWithDataProvider(fontprov);
    if cgfont.is_null() { fail "could not create quartz font" }
    dtor = fn@(move dtor) { CGFontRelease(cgfont); dtor() };

    let cface = cairo_quartz_font_face_create_for_cgfont(cgfont);
    assert cface.is_not_null(); // FIXME: error handling
    dtor = fn@(move dtor) { cairo_font_face_destroy(cface); dtor() };

    (cface, dtor)
}

fn create_test_font() -> Font {
    Font(test_font_bin())
}

fn test_font_bin() -> [u8] { #include_bin("JosefinSans-SemiBold.ttf") }

fn should_destruct_on_fail_without_leaking() {
    #[test];
    #[should_fail];
    #[ignore];

    let _font = create_test_font();
    fail;
}

fn should_get_glyph_indexes() {
    #[test];

    let font = create_test_font();
    let glyph_idx = font.glyph_idx('w');
    assert glyph_idx == some(40u);
}

fn should_get_glyph_advance() {
    #[test];
    #[ignore(reason = "random failures")];

    let font = create_test_font();
    let x = font.glyph_h_advance(40u);
    assert x == 15;
}

fn should_be_able_to_create_instances_in_multiple_threads() {
    #[test];

    iter::repeat(10u) {||
        task::spawn {||
            create_test_font();
        }
    }
}

fn get_cairo_face_should_fail_and_not_leak_if_font_cant_be_created() {
    #[test];
    #[should_fail];

    get_cairo_face(&[0u8, 1u8, 2u8, 3u8]);
}

fn get_cairo_face_should_return_a_new_face_and_dtor() {
    #[test];

    let buf = test_font_bin();
    let (face, dtor) = get_cairo_face(&buf);
    assert face.is_not_null();
    dtor();
}

fn get_cairo_font_should_return_a_new_font_and_dtor() {
    #[test];

    let buf = test_font_bin();
    let (font, dtor) = get_cairo_font(&buf);
    assert font.is_not_null();
    dtor();
}
<commit_msg>Convert Font from a class to a resource + impl to avoid bugs<commit_after>export Font, create_test_font, test_font_bin;

import glyph::GlyphIndex;
import vec_to_ptr = vec::unsafe::to_ptr;
import libc::{ c_int, c_double, c_ulong };
import ptr::{ null, addr_of };
import azure::cairo::{
    cairo_font_face_t,
    cairo_scaled_font_t,
    cairo_glyph_t,
    cairo_text_extents_t,
    CAIRO_STATUS_SUCCESS,
};
import azure::cairo::bindgen::{
    cairo_font_face_destroy,
    cairo_scaled_font_destroy,
    cairo_scaled_font_status,
    cairo_scaled_font_text_to_glyphs,
    cairo_scaled_font_glyph_extents,
    cairo_glyph_free,
    cairo_status_to_string
};

// FIXME (rust 2708): convert this to a class

type Font = FontDtor;

#[doc = "
A font handle. Layout can use this to calculate glyph metrics
and the renderer can use it to render text.
"]
resource FontDtor(state: FontState) {
    state.font_dtor();
}

type FontState = {
    fontbuf: @[u8],
    cairo_font: *cairo_scaled_font_t,
    font_dtor: fn@()
};

fn Font(-fontbuf: [u8]) -> Font {
    let (cairo_font, font_dtor) = get_cairo_font(&copy fontbuf);
    assert cairo_font.is_not_null();

    ret FontDtor({
        fontbuf: @fontbuf,
        cairo_font: cairo_font,
        font_dtor: font_dtor
    });
}

impl Font for Font {
    fn buf() -> @[u8] {
        self.fontbuf
    }

    fn glyph_idx(codepoint: char) -> option<GlyphIndex> {
        #debug("getting glyph for codepoint %u", codepoint as uint);
        let codepoint_str = str::from_char(codepoint);

        let mut glyphs: *cairo_glyph_t = null();
        let mut num_glyphs = 0 as c_int;

        let status = str::as_c_str(codepoint_str) { |codepoint_buf|
            cairo_scaled_font_text_to_glyphs(
                self.cairo_font,
                0.0 as c_double, 0.0 as c_double,
                codepoint_buf, codepoint_str.len() as c_int,
                addr_of(glyphs), addr_of(num_glyphs),
                null(), null(), null()
            )
        };

        ret if status == CAIRO_STATUS_SUCCESS {

            // This might not be true, but at least we'll know if it isn't
            assert num_glyphs == 1 as c_int;

            let glyph_index = unsafe { *glyphs }.index as GlyphIndex;
            #debug("glyph index is %?", glyph_index);
            cairo_glyph_free(glyphs);
            some(glyph_index)
        } else {
            #error("cairo did not give me a glyph for %u", codepoint as uint);
            none
        }
    }

    fn glyph_h_advance(glyph: GlyphIndex) -> int {

        #debug("getting h advance for glyph %?", glyph);

        let glyphs: [cairo_glyph_t] = [{
            index: glyph as c_ulong,
            x: 0 as c_double,
            y: 0 as c_double,
        }];
        let extents: cairo_text_extents_t = {
            x_bearing: 0 as c_double,
            y_bearing: 0 as c_double,
            width: 0 as c_double,
            height: 0 as c_double,
            x_advance: 0 as c_double,
            y_advance: 0 as c_double,
        };

        assert self.cairo_font.is_not_null();

        cairo_scaled_font_glyph_extents(
            self.cairo_font, unsafe { vec_to_ptr(glyphs) },
            1 as c_int, addr_of(extents));

        alt cairo_scaled_font_status(self.cairo_font) {
          status if status == CAIRO_STATUS_SUCCESS {

            #debug("x_advance: %?", extents.x_advance);
            #debug("y_advance: %?", extents.y_advance);

            ret extents.x_advance as int;
          }
         status {
            import str::unsafe::from_c_str;

            let status_cstr = cairo_status_to_string(status);
            let status_str = unsafe { from_c_str(status_cstr) };

            #error("cairo_scaled_font_glyph_extents status: %s", status_str);
            fail "failed to get glyph extents from cairo"
          }
        }
    }
}

fn get_cairo_font(buf: &[u8]) -> (*cairo_scaled_font_t, fn@()) {

    import libc::c_double;
    import azure::cairo;
    import cairo::{ cairo_matrix_t };
    import cairo::bindgen::{
        cairo_matrix_init_identity,
        cairo_matrix_scale,
        cairo_font_options_create,
        cairo_font_options_destroy,
        cairo_scaled_font_create,
        cairo_scaled_font_destroy
    };

    import cairo::bindgen::cairo_scaled_font_create;

    let mut (face, dtor) = get_cairo_face(buf);

    let idmatrix: cairo_matrix_t = {
        xx: 0 as c_double,
        yx: 0 as c_double,
        xy: 0 as c_double,
        yy: 0 as c_double,
        x0: 0 as c_double,
        y0: 0 as c_double
    };
    cairo_matrix_init_identity(addr_of(idmatrix));

    let fontmatrix = idmatrix;
    cairo_matrix_scale(addr_of(fontmatrix),
                       20f as c_double, 20f as c_double);

    let options = cairo_font_options_create();
    let cfont = cairo_scaled_font_create(face, addr_of(fontmatrix),
                                         addr_of(idmatrix), options);
    cairo_font_options_destroy(options);

    // FIXME: Need negative tests
    if cfont.is_null() {
        dtor();
        fail "unable to create cairo scaled font";
    }
    dtor = fn@(move dtor) { cairo_scaled_font_destroy(cfont); dtor() };

    (cfont, dtor)
}

#[cfg(target_os = "linux")]
fn get_cairo_face(buf: &[u8]) -> (*cairo_font_face_t, fn@()) {
    import freetype = azure::freetype;
    import freetype::{ FT_Error, FT_Library, FT_Face, FT_Long };
    import freetype::bindgen::{
        FT_Init_FreeType,
        FT_Done_FreeType,
        FT_New_Memory_Face,
        FT_Done_Face
    };
    import azure::cairo_ft;
    import cairo_ft::bindgen::cairo_ft_font_face_create_for_ft_face;

    impl methods for FT_Error {
        fn for_sure() { assert !self.failed() }
        fn failed() -> bool { self != 0 as FT_Error }
    }

    let mut dtor = fn@() { };

    let library: FT_Library = null();
    // FIXME: Need tests for failure case
    FT_Init_FreeType(addr_of(library)).for_sure();
    dtor = fn@(move dtor) { FT_Done_FreeType(library).for_sure(); dtor() };

    let face: FT_Face = null();
    vec::as_buf(*buf) { |cbuf|
        if FT_New_Memory_Face(library, cbuf, (*buf).len() as FT_Long,
                              0 as FT_Long, addr_of(face)).failed() {
            dtor();
            fail "unable to create FreeType face";
        }
    }
    dtor = fn@(move dtor) { FT_Done_Face(face).for_sure(); dtor() };

    let cface = cairo_ft_font_face_create_for_ft_face(face, 0 as c_int);
    if cface.is_null() {
        // FIXME: Need tests for failure case
        dtor();
        fail "unable to create cairo font face";
    }
    dtor = fn@(move dtor) { cairo_font_face_destroy(cface); dtor() };

    (cface, dtor)
}

#[cfg(target_os = "macos")]
mod cocoa {
    use cocoa;
    export cocoa;
}

#[cfg(target_os = "macos")]
fn get_cairo_face(buf: &[u8]) -> (*cairo_font_face_t, fn@()) {
    import unsafe::reinterpret_cast;
    import libc::size_t;
    import cocoa::cocoa;
    import cocoa::cg::cg::{
        CGDataProviderCreateWithData,
        CGDataProviderRelease,
        CGFontCreateWithDataProvider,
        CGFontRelease
    };
    import azure::cairo_quartz::bindgen::cairo_quartz_font_face_create_for_cgfont;

    let mut dtor = fn@() { };

    let fontprov = vec::as_buf(*buf) { |cbuf|
        CGDataProviderCreateWithData(
            null(),
            unsafe { reinterpret_cast(cbuf) },
            (*buf).len() as size_t,
            null()
        )
    };
    dtor = fn@(move dtor) { CGDataProviderRelease(fontprov); dtor() };

    let cgfont = CGFontCreateWithDataProvider(fontprov);
    if cgfont.is_null() { fail "could not create quartz font" }
    dtor = fn@(move dtor) { CGFontRelease(cgfont); dtor() };

    let cface = cairo_quartz_font_face_create_for_cgfont(cgfont);
    assert cface.is_not_null(); // FIXME: error handling
    dtor = fn@(move dtor) { cairo_font_face_destroy(cface); dtor() };

    (cface, dtor)
}

fn create_test_font() -> Font {
    Font(test_font_bin())
}

fn test_font_bin() -> [u8] { #include_bin("JosefinSans-SemiBold.ttf") }

fn should_destruct_on_fail_without_leaking() {
    #[test];
    #[should_fail];
    #[ignore];

    let _font = create_test_font();
    fail;
}

fn should_get_glyph_indexes() {
    #[test];

    let font = create_test_font();
    let glyph_idx = font.glyph_idx('w');
    assert glyph_idx == some(40u);
}

fn should_get_glyph_advance() {
    #[test];
    #[ignore(reason = "random failures")];

    let font = create_test_font();
    let x = font.glyph_h_advance(40u);
    assert x == 15;
}

fn should_be_able_to_create_instances_in_multiple_threads() {
    #[test];

    iter::repeat(10u) {||
        task::spawn {||
            create_test_font();
        }
    }
}

fn get_cairo_face_should_fail_and_not_leak_if_font_cant_be_created() {
    #[test];
    #[should_fail];

    get_cairo_face(&[0u8, 1u8, 2u8, 3u8]);
}

fn get_cairo_face_should_return_a_new_face_and_dtor() {
    #[test];

    let buf = test_font_bin();
    let (face, dtor) = get_cairo_face(&buf);
    assert face.is_not_null();
    dtor();
}

fn get_cairo_font_should_return_a_new_font_and_dtor() {
    #[test];

    let buf = test_font_bin();
    let (font, dtor) = get_cairo_font(&buf);
    assert font.is_not_null();
    dtor();
}
<|endoftext|>


<commit_before><commit_msg>Remove extraneous uniform block type<commit_after><|endoftext|>


<commit_before>use std::error::Error;
use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;
use std::fs::File as FSFile;
use std::io::Read;
use std::io::Write;

use glob::glob;
use glob::Paths;

use storage::file::File;
use storage::file_id::*;
use storage::parser::{FileHeaderParser, Parser, ParserError};

use module::Module;
use runtime::Runtime;

pub type BackendOperationResult = Result<(), StorageBackendError>;

pub struct StorageBackend {
    basepath: String,
}

impl StorageBackend {

    pub fn new(basepath: String) -> StorageBackend {
        StorageBackend {
            basepath: basepath,
        }
    }

    fn build<M: Module>(rt: &Runtime, m: &M) -> StorageBackend {
        let path = rt.get_rtp() + m.name() + "/store";
        StorageBackend::new(path)
    }

    fn get_file_ids(&self) -> Option<Vec<FileID>> {
        let list = glob(&self.basepath[..]);

        if let Ok(globlist) = list {
            let mut v = vec![];
            for entry in globlist {
                if let Ok(path) = entry {
                    v.push(from_pathbuf(&path));
                } else {
                    // Entry is not a path
                }
            }

            Some(v)
        } else {
            None
        }
    }

    /*
     * Write a file to disk.
     *
     * The file is moved to this function as the file won't be edited afterwards
     */
    pub fn put_file<'a, HP>(&self, f: File, p: &Parser<HP>) ->
        Result<BackendOperationResult, ParserError>
        where HP: FileHeaderParser<'a>
    {
        let written = p.write(f.contents());
        if let Ok(string) = written {
            let path = self.build_filepath(&f);
            debug!("Writing file: {}", path);
            Ok(Ok(()))
        } else {
            Err(written.err().unwrap())
        }
    }

    /*
     * Update a file. We have the UUID and can find the file on FS with it and
     * then replace its contents with the contents of the passed file object
     */
    pub fn update_file<'a, HP>(&self, f: File, p: &Parser<HP>)
        -> Result<BackendOperationResult, ParserError>
        where HP: FileHeaderParser<'a>
    {
        let contents = p.write(f.contents());

        if contents.is_err() {
            return Err(contents.err().unwrap());
        }

        let content = contents.unwrap();

        let path = self.build_filepath(&f);
        if let Err(_) = FSFile::open(path) {
            return Ok(Err(StorageBackendError::new(
                "File::open()",
                &format!("Tried to open '{}'", path)[..],
                "Tried to update contents of this file, though file doesn't exist",
                None)))
        }

        if let Ok(mut file) = FSFile::create(path) {
            if let Err(writeerr) = file.write_all(&content.into_bytes()) {
                return Ok(Err(StorageBackendError::new(
                    "File::write()",
                    &format!("Tried to write '{}'", path)[..],
                    "Tried to write contents of this file, though operation did not succeed",
                    Some(content))))
            }
        }

        Ok(Ok(()))
    }

    /*
     * Find a file by its ID and return it if found. Return nothing if not
     * found, of course.
     *
     * TODO: Needs refactoring, as there might be an error when reading from
     * disk OR the id just does not exist.
     */
    pub fn get_file_by_id<'a, HP>(&self, id: FileID, p: &Parser<HP>) -> Option<File>
        where HP: FileHeaderParser<'a>
    {
        if let Ok(fs) = FSFile::open(self.build_filepath_with_id(id)) {
            let mut s = String::new();
            fs.read_to_string(&mut s);
            p.read(s).and_then(|(h, d)| Ok(File::from_parser_result(id, h, d))).ok()
        } else {
            None
        }
    }

    fn build_filepath(&self, f: &File) -> String {
        self.build_filepath_with_id(f.id())
    }

    fn build_filepath_with_id(&self, id: FileID) -> String {
        self.basepath + &id[..]
    }

}

#[derive(Debug)]
pub struct StorageBackendError {
    pub action: String,             // The file system action in words
    pub desc: String,               // A short description
    pub explanation: String,        // A long, user friendly description
    pub dataDump: Option<String>    // Data dump, if any
}

impl StorageBackendError {
    fn new(action: &'static str,
           desc  : &'static str,
           explan: &'static str,
           data  : Option<String>) -> StorageBackendError
    {
        StorageBackendError {
            action:         String::from(action),
            desc:           String::from(desc),
            explanation:    String::from(explan),
            dataDump:       data,
        }
    }
}

impl Error for StorageBackendError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for StorageBackendError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "StorageBackendError[{}]: {}\n\n{}",
               self.action, self.desc, self.explanation)
    }
}

<commit_msg>StorageBackendError: Use String instead of str in params<commit_after>use std::error::Error;
use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;
use std::fs::File as FSFile;
use std::io::Read;
use std::io::Write;

use glob::glob;
use glob::Paths;

use storage::file::File;
use storage::file_id::*;
use storage::parser::{FileHeaderParser, Parser, ParserError};

use module::Module;
use runtime::Runtime;

pub type BackendOperationResult = Result<(), StorageBackendError>;

pub struct StorageBackend {
    basepath: String,
}

impl StorageBackend {

    pub fn new(basepath: String) -> StorageBackend {
        StorageBackend {
            basepath: basepath,
        }
    }

    fn build<M: Module>(rt: &Runtime, m: &M) -> StorageBackend {
        let path = rt.get_rtp() + m.name() + "/store";
        StorageBackend::new(path)
    }

    fn get_file_ids(&self) -> Option<Vec<FileID>> {
        let list = glob(&self.basepath[..]);

        if let Ok(globlist) = list {
            let mut v = vec![];
            for entry in globlist {
                if let Ok(path) = entry {
                    v.push(from_pathbuf(&path));
                } else {
                    // Entry is not a path
                }
            }

            Some(v)
        } else {
            None
        }
    }

    /*
     * Write a file to disk.
     *
     * The file is moved to this function as the file won't be edited afterwards
     */
    pub fn put_file<'a, HP>(&self, f: File, p: &Parser<HP>) ->
        Result<BackendOperationResult, ParserError>
        where HP: FileHeaderParser<'a>
    {
        let written = p.write(f.contents());
        if let Ok(string) = written {
            let path = self.build_filepath(&f);
            debug!("Writing file: {}", path);
            Ok(Ok(()))
        } else {
            Err(written.err().unwrap())
        }
    }

    /*
     * Update a file. We have the UUID and can find the file on FS with it and
     * then replace its contents with the contents of the passed file object
     */
    pub fn update_file<'a, HP>(&self, f: File, p: &Parser<HP>)
        -> Result<BackendOperationResult, ParserError>
        where HP: FileHeaderParser<'a>
    {
        let contents = p.write(f.contents());

        if contents.is_err() {
            return Err(contents.err().unwrap());
        }

        let content = contents.unwrap();

        let path = self.build_filepath(&f);
        if let Err(_) = FSFile::open(path) {
            return Ok(Err(StorageBackendError::new(
                String::from("File::open()"),
                format!("Tried to open '{}'", path),
                String::from("Tried to update contents of this file, though file doesn't exist"),
                None)))
        }

        if let Ok(mut file) = FSFile::create(path) {
            if let Err(writeerr) = file.write_all(&content.into_bytes()) {
                return Ok(Err(StorageBackendError::new(
                    String::from("File::write()"),
                    format!("Tried to write '{}'", path),
                    String::from("Tried to write contents of this file, though operation did not succeed"),
                    Some(content))))
            }
        }

        Ok(Ok(()))
    }

    /*
     * Find a file by its ID and return it if found. Return nothing if not
     * found, of course.
     *
     * TODO: Needs refactoring, as there might be an error when reading from
     * disk OR the id just does not exist.
     */
    pub fn get_file_by_id<'a, HP>(&self, id: FileID, p: &Parser<HP>) -> Option<File>
        where HP: FileHeaderParser<'a>
    {
        if let Ok(fs) = FSFile::open(self.build_filepath_with_id(id)) {
            let mut s = String::new();
            fs.read_to_string(&mut s);
            p.read(s).and_then(|(h, d)| Ok(File::from_parser_result(id, h, d))).ok()
        } else {
            None
        }
    }

    fn build_filepath(&self, f: &File) -> String {
        self.build_filepath_with_id(f.id())
    }

    fn build_filepath_with_id(&self, id: FileID) -> String {
        self.basepath + &id[..]
    }

}

#[derive(Debug)]
pub struct StorageBackendError {
    pub action: String,             // The file system action in words
    pub desc: String,               // A short description
    pub explanation: String,        // A long, user friendly description
    pub dataDump: Option<String>    // Data dump, if any
}

impl StorageBackendError {
    fn new(action: String,
           desc  : String,
           explan: String,
           data  : Option<String>) -> StorageBackendError
    {
        StorageBackendError {
            action:         action,
            desc:           desc,
            explanation:    explan,
            dataDump:       data,
        }
    }
}

impl Error for StorageBackendError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for StorageBackendError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "StorageBackendError[{}]: {}\n\n{}",
               self.action, self.desc, self.explanation)
    }
}

<|endoftext|>


<commit_before><commit_msg>Add - for range<commit_after><|endoftext|>


<commit_before><commit_msg>Make test_smoke use Poll API (#651)<commit_after><|endoftext|>


<commit_before><commit_msg>Add a simple to-device test<commit_after><|endoftext|>


<commit_before><commit_msg>delete duplicates<commit_after><|endoftext|>


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

//! See docs in build/expr/mod.rs

use rustc_data_structures::fnv::FnvHashMap;

use build::{BlockAnd, BlockAndExtension, Builder};
use build::expr::category::{Category, RvalueFunc};
use hair::*;
use rustc::mir::repr::*;

impl<'a,'tcx> Builder<'a,'tcx> {
    /// Compile `expr`, yielding an rvalue.
    pub fn as_rvalue<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Rvalue<'tcx>>
        where M: Mirror<'tcx, Output = Expr<'tcx>>
    {
        let expr = self.hir.mirror(expr);
        self.expr_as_rvalue(block, expr)
    }

    fn expr_as_rvalue(&mut self,
                      mut block: BasicBlock,
                      expr: Expr<'tcx>)
                      -> BlockAnd<Rvalue<'tcx>> {
        debug!("expr_as_rvalue(block={:?}, expr={:?})", block, expr);

        let this = self;
        let expr_span = expr.span;

        match expr.kind {
            ExprKind::Scope { extent, value } => {
                this.in_scope(extent, block, |this| this.as_rvalue(block, value))
            }
            ExprKind::InlineAsm { asm } => {
                block.and(Rvalue::InlineAsm(asm.clone()))
            }
            ExprKind::Repeat { value, count } => {
                let value_operand = unpack!(block = this.as_operand(block, value));
                block.and(Rvalue::Repeat(value_operand, count))
            }
            ExprKind::Borrow { region, borrow_kind, arg } => {
                let arg_lvalue = unpack!(block = this.as_lvalue(block, arg));
                block.and(Rvalue::Ref(region, borrow_kind, arg_lvalue))
            }
            ExprKind::Binary { op, lhs, rhs } => {
                let lhs = unpack!(block = this.as_operand(block, lhs));
                let rhs = unpack!(block = this.as_operand(block, rhs));
                block.and(Rvalue::BinaryOp(op, lhs, rhs))
            }
            ExprKind::Unary { op, arg } => {
                let arg = unpack!(block = this.as_operand(block, arg));
                block.and(Rvalue::UnaryOp(op, arg))
            }
            ExprKind::Box { value } => {
                let value = this.hir.mirror(value);
                let value_ty = value.ty.clone();
                let result = this.temp(value_ty.clone());

                // to start, malloc some memory of suitable type (thus far, uninitialized):
                let rvalue = Rvalue::Box(value.ty.clone());
                this.cfg.push_assign(block, expr_span, &result, rvalue);

                // schedule a shallow free of that memory, lest we unwind:
                let extent = this.extent_of_innermost_scope();
                this.schedule_drop(expr_span, extent, DropKind::Free, &result, value_ty);

                // initialize the box contents:
                let contents = result.clone().deref();
                unpack!(block = this.into(&contents, block, value));

                // now that the result is fully initialized, cancel the drop
                // by "using" the result (which is linear):
                block.and(Rvalue::Use(Operand::Consume(result)))
            }
            ExprKind::Cast { source } => {
                let source = unpack!(block = this.as_operand(block, source));
                block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty))
            }
            ExprKind::ReifyFnPointer { source } => {
                let source = unpack!(block = this.as_operand(block, source));
                block.and(Rvalue::Cast(CastKind::ReifyFnPointer, source, expr.ty))
            }
            ExprKind::UnsafeFnPointer { source } => {
                let source = unpack!(block = this.as_operand(block, source));
                block.and(Rvalue::Cast(CastKind::UnsafeFnPointer, source, expr.ty))
            }
            ExprKind::Unsize { source } => {
                let source = unpack!(block = this.as_operand(block, source));
                block.and(Rvalue::Cast(CastKind::Unsize, source, expr.ty))
            }
            ExprKind::Vec { fields } => {
                // (*) We would (maybe) be closer to trans if we
                // handled this and other aggregate cases via
                // `into()`, not `as_rvalue` -- in that case, instead
                // of generating
                //
                //     let tmp1 = ...1;
                //     let tmp2 = ...2;
                //     dest = Rvalue::Aggregate(Foo, [tmp1, tmp2])
                //
                // we could just generate
                //
                //     dest.f = ...1;
                //     dest.g = ...2;
                //
                // The problem is that then we would need to:
                //
                // (a) have a more complex mechanism for handling
                //     partial cleanup;
                // (b) distinguish the case where the type `Foo` has a
                //     destructor, in which case creating an instance
                //     as a whole "arms" the destructor, and you can't
                //     write individual fields; and,
                // (c) handle the case where the type Foo has no
                //     fields. We don't want `let x: ();` to compile
                //     to the same MIR as `let x = ();`.

                // first process the set of fields
                let fields: Vec<_> =
                    fields.into_iter()
                          .map(|f| unpack!(block = this.as_operand(block, f)))
                          .collect();

                block.and(Rvalue::Aggregate(AggregateKind::Vec, fields))
            }
            ExprKind::Tuple { fields } => { // see (*) above
                // first process the set of fields
                let fields: Vec<_> =
                    fields.into_iter()
                          .map(|f| unpack!(block = this.as_operand(block, f)))
                          .collect();

                block.and(Rvalue::Aggregate(AggregateKind::Tuple, fields))
            }
            ExprKind::Closure { closure_id, substs, upvars } => { // see (*) above
                let upvars =
                    upvars.into_iter()
                          .map(|upvar| unpack!(block = this.as_operand(block, upvar)))
                          .collect();
                block.and(Rvalue::Aggregate(AggregateKind::Closure(closure_id, substs), upvars))
            }
            ExprKind::Adt { adt_def, variant_index, substs, fields, base } => { // see (*) above
                // first process the set of fields that were provided
                // (evaluating them in order given by user)
                let fields_map: FnvHashMap<_, _> =
                    fields.into_iter()
                          .map(|f| (f.name, unpack!(block = this.as_operand(block, f.expr))))
                          .collect();

                // if base expression is given, evaluate it now
                let base = base.map(|base| unpack!(block = this.as_lvalue(block, base)));

                // get list of all fields that we will need
                let field_names = this.hir.all_fields(adt_def, variant_index);

                // for the actual values we use, take either the
                // expr the user specified or, if they didn't
                // specify something for this field name, create a
                // path relative to the base (which must have been
                // supplied, or the IR is internally
                // inconsistent).
                let fields: Vec<_> =
                    field_names.into_iter()
                               .map(|n| match fields_map.get(&n) {
                                   Some(v) => v.clone(),
                                   None => Operand::Consume(base.clone().unwrap().field(n)),
                               })
                               .collect();

                block.and(Rvalue::Aggregate(AggregateKind::Adt(adt_def, variant_index, substs),
                                            fields))
            }
            ExprKind::Literal { .. } |
            ExprKind::Block { .. } |
            ExprKind::Match { .. } |
            ExprKind::If { .. } |
            ExprKind::Loop { .. } |
            ExprKind::LogicalOp { .. } |
            ExprKind::Call { .. } |
            ExprKind::Field { .. } |
            ExprKind::Deref { .. } |
            ExprKind::Index { .. } |
            ExprKind::VarRef { .. } |
            ExprKind::SelfRef |
            ExprKind::Assign { .. } |
            ExprKind::AssignOp { .. } |
            ExprKind::Break { .. } |
            ExprKind::Continue { .. } |
            ExprKind::Return { .. } |
            ExprKind::StaticRef { .. } => {
                // these do not have corresponding `Rvalue` variants,
                // so make an operand and then return that
                debug_assert!(match Category::of(&expr.kind) {
                    Some(Category::Rvalue(RvalueFunc::AsRvalue)) => false,
                    _ => true,
                });
                let operand = unpack!(block = this.as_operand(block, expr));
                block.and(Rvalue::Use(operand))
            }
        }
    }
}
<commit_msg>[MIR] Fix type of temporary for `box EXPR`<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! See docs in build/expr/mod.rs

use rustc_data_structures::fnv::FnvHashMap;

use build::{BlockAnd, BlockAndExtension, Builder};
use build::expr::category::{Category, RvalueFunc};
use hair::*;
use rustc::mir::repr::*;

impl<'a,'tcx> Builder<'a,'tcx> {
    /// Compile `expr`, yielding an rvalue.
    pub fn as_rvalue<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Rvalue<'tcx>>
        where M: Mirror<'tcx, Output = Expr<'tcx>>
    {
        let expr = self.hir.mirror(expr);
        self.expr_as_rvalue(block, expr)
    }

    fn expr_as_rvalue(&mut self,
                      mut block: BasicBlock,
                      expr: Expr<'tcx>)
                      -> BlockAnd<Rvalue<'tcx>> {
        debug!("expr_as_rvalue(block={:?}, expr={:?})", block, expr);

        let this = self;
        let expr_span = expr.span;

        match expr.kind {
            ExprKind::Scope { extent, value } => {
                this.in_scope(extent, block, |this| this.as_rvalue(block, value))
            }
            ExprKind::InlineAsm { asm } => {
                block.and(Rvalue::InlineAsm(asm.clone()))
            }
            ExprKind::Repeat { value, count } => {
                let value_operand = unpack!(block = this.as_operand(block, value));
                block.and(Rvalue::Repeat(value_operand, count))
            }
            ExprKind::Borrow { region, borrow_kind, arg } => {
                let arg_lvalue = unpack!(block = this.as_lvalue(block, arg));
                block.and(Rvalue::Ref(region, borrow_kind, arg_lvalue))
            }
            ExprKind::Binary { op, lhs, rhs } => {
                let lhs = unpack!(block = this.as_operand(block, lhs));
                let rhs = unpack!(block = this.as_operand(block, rhs));
                block.and(Rvalue::BinaryOp(op, lhs, rhs))
            }
            ExprKind::Unary { op, arg } => {
                let arg = unpack!(block = this.as_operand(block, arg));
                block.and(Rvalue::UnaryOp(op, arg))
            }
            ExprKind::Box { value } => {
                let value = this.hir.mirror(value);
                let result = this.temp(expr.ty);

                // to start, malloc some memory of suitable type (thus far, uninitialized):
                let rvalue = Rvalue::Box(value.ty);
                this.cfg.push_assign(block, expr_span, &result, rvalue);

                // schedule a shallow free of that memory, lest we unwind:
                let extent = this.extent_of_innermost_scope();
                this.schedule_drop(expr_span, extent, DropKind::Free, &result, value.ty);

                // initialize the box contents:
                let contents = result.clone().deref();
                unpack!(block = this.into(&contents, block, value));

                // now that the result is fully initialized, cancel the drop
                // by "using" the result (which is linear):
                block.and(Rvalue::Use(Operand::Consume(result)))
            }
            ExprKind::Cast { source } => {
                let source = unpack!(block = this.as_operand(block, source));
                block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty))
            }
            ExprKind::ReifyFnPointer { source } => {
                let source = unpack!(block = this.as_operand(block, source));
                block.and(Rvalue::Cast(CastKind::ReifyFnPointer, source, expr.ty))
            }
            ExprKind::UnsafeFnPointer { source } => {
                let source = unpack!(block = this.as_operand(block, source));
                block.and(Rvalue::Cast(CastKind::UnsafeFnPointer, source, expr.ty))
            }
            ExprKind::Unsize { source } => {
                let source = unpack!(block = this.as_operand(block, source));
                block.and(Rvalue::Cast(CastKind::Unsize, source, expr.ty))
            }
            ExprKind::Vec { fields } => {
                // (*) We would (maybe) be closer to trans if we
                // handled this and other aggregate cases via
                // `into()`, not `as_rvalue` -- in that case, instead
                // of generating
                //
                //     let tmp1 = ...1;
                //     let tmp2 = ...2;
                //     dest = Rvalue::Aggregate(Foo, [tmp1, tmp2])
                //
                // we could just generate
                //
                //     dest.f = ...1;
                //     dest.g = ...2;
                //
                // The problem is that then we would need to:
                //
                // (a) have a more complex mechanism for handling
                //     partial cleanup;
                // (b) distinguish the case where the type `Foo` has a
                //     destructor, in which case creating an instance
                //     as a whole "arms" the destructor, and you can't
                //     write individual fields; and,
                // (c) handle the case where the type Foo has no
                //     fields. We don't want `let x: ();` to compile
                //     to the same MIR as `let x = ();`.

                // first process the set of fields
                let fields: Vec<_> =
                    fields.into_iter()
                          .map(|f| unpack!(block = this.as_operand(block, f)))
                          .collect();

                block.and(Rvalue::Aggregate(AggregateKind::Vec, fields))
            }
            ExprKind::Tuple { fields } => { // see (*) above
                // first process the set of fields
                let fields: Vec<_> =
                    fields.into_iter()
                          .map(|f| unpack!(block = this.as_operand(block, f)))
                          .collect();

                block.and(Rvalue::Aggregate(AggregateKind::Tuple, fields))
            }
            ExprKind::Closure { closure_id, substs, upvars } => { // see (*) above
                let upvars =
                    upvars.into_iter()
                          .map(|upvar| unpack!(block = this.as_operand(block, upvar)))
                          .collect();
                block.and(Rvalue::Aggregate(AggregateKind::Closure(closure_id, substs), upvars))
            }
            ExprKind::Adt { adt_def, variant_index, substs, fields, base } => { // see (*) above
                // first process the set of fields that were provided
                // (evaluating them in order given by user)
                let fields_map: FnvHashMap<_, _> =
                    fields.into_iter()
                          .map(|f| (f.name, unpack!(block = this.as_operand(block, f.expr))))
                          .collect();

                // if base expression is given, evaluate it now
                let base = base.map(|base| unpack!(block = this.as_lvalue(block, base)));

                // get list of all fields that we will need
                let field_names = this.hir.all_fields(adt_def, variant_index);

                // for the actual values we use, take either the
                // expr the user specified or, if they didn't
                // specify something for this field name, create a
                // path relative to the base (which must have been
                // supplied, or the IR is internally
                // inconsistent).
                let fields: Vec<_> =
                    field_names.into_iter()
                               .map(|n| match fields_map.get(&n) {
                                   Some(v) => v.clone(),
                                   None => Operand::Consume(base.clone().unwrap().field(n)),
                               })
                               .collect();

                block.and(Rvalue::Aggregate(AggregateKind::Adt(adt_def, variant_index, substs),
                                            fields))
            }
            ExprKind::Literal { .. } |
            ExprKind::Block { .. } |
            ExprKind::Match { .. } |
            ExprKind::If { .. } |
            ExprKind::Loop { .. } |
            ExprKind::LogicalOp { .. } |
            ExprKind::Call { .. } |
            ExprKind::Field { .. } |
            ExprKind::Deref { .. } |
            ExprKind::Index { .. } |
            ExprKind::VarRef { .. } |
            ExprKind::SelfRef |
            ExprKind::Assign { .. } |
            ExprKind::AssignOp { .. } |
            ExprKind::Break { .. } |
            ExprKind::Continue { .. } |
            ExprKind::Return { .. } |
            ExprKind::StaticRef { .. } => {
                // these do not have corresponding `Rvalue` variants,
                // so make an operand and then return that
                debug_assert!(match Category::of(&expr.kind) {
                    Some(Category::Rvalue(RvalueFunc::AsRvalue)) => false,
                    _ => true,
                });
                let operand = unpack!(block = this.as_operand(block, expr));
                block.and(Rvalue::Use(operand))
            }
        }
    }
}
<|endoftext|>


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

//! See docs in build/expr/mod.rs

use build::{BlockAnd, BlockAndExtension, Builder};
use build::expr::category::{Category, RvalueFunc};
use build::scope::LoopScope;
use hair::*;
use rustc::middle::region::CodeExtent;
use rustc::middle::ty;
use rustc::mir::repr::*;
use syntax::codemap::Span;

impl<'a,'tcx> Builder<'a,'tcx> {
    /// Compile `expr`, storing the result into `destination`, which
    /// is assumed to be uninitialized.
    pub fn into_expr(&mut self,
                     destination: &Lvalue<'tcx>,
                     mut block: BasicBlock,
                     expr: Expr<'tcx>)
                     -> BlockAnd<()>
    {
        debug!("into_expr(destination={:?}, block={:?}, expr={:?})",
               destination, block, expr);

        // since we frequently have to reference `self` from within a
        // closure, where `self` would be shadowed, it's easier to
        // just use the name `this` uniformly
        let this = self;
        let expr_span = expr.span;

        match expr.kind {
            ExprKind::Scope { extent, value } => {
                this.in_scope(extent, block, |this| this.into(destination, block, value))
            }
            ExprKind::Block { body: ast_block } => {
                this.ast_block(destination, block, ast_block)
            }
            ExprKind::Match { discriminant, arms } => {
                this.match_expr(destination, expr_span, block, discriminant, arms)
            }
            ExprKind::If { condition: cond_expr, then: then_expr, otherwise: else_expr } => {
                let operand = unpack!(block = this.as_operand(block, cond_expr));

                let mut then_block = this.cfg.start_new_block();
                let mut else_block = this.cfg.start_new_block();
                this.cfg.terminate(block, Terminator::If {
                    cond: operand,
                    targets: (then_block, else_block)
                });

                unpack!(then_block = this.into(destination, then_block, then_expr));
                else_block = if let Some(else_expr) = else_expr {
                    unpack!(this.into(destination, else_block, else_expr))
                } else {
                    // Body of the `if` expression without an `else` clause must return `()`, thus
                    // we implicitly generate a `else {}` if it is not specified.
                    this.cfg.push_assign_unit(else_block, expr_span, &Lvalue::ReturnPointer);
                    else_block
                };

                let join_block = this.cfg.start_new_block();
                this.cfg.terminate(then_block, Terminator::Goto { target: join_block });
                this.cfg.terminate(else_block, Terminator::Goto { target: join_block });

                join_block.unit()
            }
            ExprKind::LogicalOp { op, lhs, rhs } => {
                // And:
                //
                // [block: If(lhs)] -true-> [else_block: If(rhs)] -true-> [true_block]
                //        |                          | (false)
                //        +----------false-----------+------------------> [false_block]
                //
                // Or:
                //
                // [block: If(lhs)] -false-> [else_block: If(rhs)] -true-> [true_block]
                //        |                          | (false)
                //        +----------true------------+-------------------> [false_block]

                let (true_block, false_block, mut else_block, join_block) =
                    (this.cfg.start_new_block(), this.cfg.start_new_block(),
                     this.cfg.start_new_block(), this.cfg.start_new_block());

                let lhs = unpack!(block = this.as_operand(block, lhs));
                let blocks = match op {
                    LogicalOp::And => (else_block, false_block),
                    LogicalOp::Or => (true_block, else_block),
                };
                this.cfg.terminate(block, Terminator::If { cond: lhs, targets: blocks });

                let rhs = unpack!(else_block = this.as_operand(else_block, rhs));
                this.cfg.terminate(else_block, Terminator::If {
                    cond: rhs,
                    targets: (true_block, false_block)
                });

                this.cfg.push_assign_constant(
                    true_block, expr_span, destination,
                    Constant {
                        span: expr_span,
                        ty: this.hir.bool_ty(),
                        literal: this.hir.true_literal(),
                    });

                this.cfg.push_assign_constant(
                    false_block, expr_span, destination,
                    Constant {
                        span: expr_span,
                        ty: this.hir.bool_ty(),
                        literal: this.hir.false_literal(),
                    });

                this.cfg.terminate(true_block, Terminator::Goto { target: join_block });
                this.cfg.terminate(false_block, Terminator::Goto { target: join_block });

                join_block.unit()
            }
            ExprKind::Loop { condition: opt_cond_expr, body } => {
                // [block] --> [loop_block] ~~> [loop_block_end] -1-> [exit_block]
                //                  ^                  |
                //                  |                  0
                //                  |                  |
                //                  |                  v
                //           [body_block_end] <~~~ [body_block]
                //
                // If `opt_cond_expr` is `None`, then the graph is somewhat simplified:
                //
                // [block] --> [loop_block / body_block ] ~~> [body_block_end]    [exit_block]
                //                         ^                          |
                //                         |                          |
                //                         +--------------------------+
                //

                let loop_block = this.cfg.start_new_block();
                let exit_block = this.cfg.start_new_block();

                // start the loop
                this.cfg.terminate(block, Terminator::Goto { target: loop_block });

                let might_break = this.in_loop_scope(loop_block, exit_block, move |this| {
                    // conduct the test, if necessary
                    let body_block;
                    if let Some(cond_expr) = opt_cond_expr {
                        // This loop has a condition, ergo its exit_block is reachable.
                        this.find_loop_scope(expr_span, None).might_break = true;

                        let loop_block_end;
                        let cond = unpack!(loop_block_end = this.as_operand(loop_block, cond_expr));
                        body_block = this.cfg.start_new_block();
                        this.cfg.terminate(loop_block_end,
                                           Terminator::If {
                                               cond: cond,
                                               targets: (body_block, exit_block)
                                           });
                    } else {
                        body_block = loop_block;
                    }

                    // The “return” value of the loop body must always be an unit, but we cannot
                    // reuse that as a “return” value of the whole loop expressions, because some
                    // loops are diverging (e.g. `loop {}`). Thus, we introduce a unit temporary as
                    // the destination for the loop body and assign the loop’s own “return” value
                    // immediately after the iteration is finished.
                    let tmp = this.get_unit_temp();
                    // Execute the body, branching back to the test.
                    let body_block_end = unpack!(this.into(&tmp, body_block, body));
                    this.cfg.terminate(body_block_end, Terminator::Goto { target: loop_block });
                });
                // If the loop may reach its exit_block, we assign an empty tuple to the
                // destination to keep the MIR well-formed.
                if might_break {
                    this.cfg.push_assign_unit(exit_block, expr_span, destination);
                }
                exit_block.unit()
            }
            ExprKind::Assign { lhs, rhs } => {
                // Note: we evaluate assignments right-to-left. This
                // is better for borrowck interaction with overloaded
                // operators like x[j] = x[i].
                let rhs = unpack!(block = this.as_operand(block, rhs));
                let lhs = unpack!(block = this.as_lvalue(block, lhs));
                unpack!(block = this.build_drop(block, lhs.clone()));
                this.cfg.push_assign(block, expr_span, &lhs, Rvalue::Use(rhs));
                block.unit()
            }
            ExprKind::AssignOp { op, lhs, rhs } => {
                // FIXME(#28160) there is an interesting semantics
                // question raised here -- should we "freeze" the
                // value of the lhs here?  I'm inclined to think not,
                // since it seems closer to the semantics of the
                // overloaded version, which takes `&mut self`.  This
                // only affects weird things like `x += {x += 1; x}`
                // -- is that equal to `x + (x + 1)` or `2*(x+1)`?

                // As above, RTL.
                let rhs = unpack!(block = this.as_operand(block, rhs));
                let lhs = unpack!(block = this.as_lvalue(block, lhs));

                // we don't have to drop prior contents or anything
                // because AssignOp is only legal for Copy types
                // (overloaded ops should be desugared into a call).
                this.cfg.push_assign(block, expr_span, &lhs,
                                     Rvalue::BinaryOp(op,
                                                      Operand::Consume(lhs.clone()),
                                                      rhs));

                block.unit()
            }
            ExprKind::Continue { label } => {
                this.break_or_continue(expr_span, label, block,
                                       |loop_scope| loop_scope.continue_block)
            }
            ExprKind::Break { label } => {
                this.break_or_continue(expr_span, label, block, |loop_scope| {
                    loop_scope.might_break = true;
                    loop_scope.break_block
                })
            }
            ExprKind::Return { value } => {
                block = match value {
                    Some(value) => unpack!(this.into(&Lvalue::ReturnPointer, block, value)),
                    None => {
                        this.cfg.push_assign_unit(block, expr_span, &Lvalue::ReturnPointer);
                        block
                    }
                };
                let extent = this.extent_of_outermost_scope();
                this.exit_scope(expr_span, extent, block, END_BLOCK);
                this.cfg.start_new_block().unit()
            }
            ExprKind::Call { ty, fun, args } => {
                let diverges = match ty.sty {
                    ty::TyBareFn(_, ref f) => f.sig.0.output.diverges(),
                    _ => false
                };
                let fun = unpack!(block = this.as_operand(block, fun));
                let args: Vec<_> =
                    args.into_iter()
                        .map(|arg| unpack!(block = this.as_operand(block, arg)))
                        .collect();

                let success = this.cfg.start_new_block();
                let cleanup = this.diverge_cleanup();
                this.cfg.terminate(block, Terminator::Call {
                    func: fun,
                    args: args,
                    cleanup: cleanup,
                    destination: if diverges {
                        None
                    } else {
                        Some ((destination.clone(), success))
                    }
                });
                success.unit()
            }

            // these are the cases that are more naturally handled by some other mode
            ExprKind::Unary { .. } |
            ExprKind::Binary { .. } |
            ExprKind::Box { .. } |
            ExprKind::Cast { .. } |
            ExprKind::ReifyFnPointer { .. } |
            ExprKind::UnsafeFnPointer { .. } |
            ExprKind::Unsize { .. } |
            ExprKind::Repeat { .. } |
            ExprKind::Borrow { .. } |
            ExprKind::VarRef { .. } |
            ExprKind::SelfRef |
            ExprKind::StaticRef { .. } |
            ExprKind::Vec { .. } |
            ExprKind::Tuple { .. } |
            ExprKind::Adt { .. } |
            ExprKind::Closure { .. } |
            ExprKind::Index { .. } |
            ExprKind::Deref { .. } |
            ExprKind::Literal { .. } |
            ExprKind::InlineAsm { .. } |
            ExprKind::Field { .. } => {
                debug_assert!(match Category::of(&expr.kind).unwrap() {
                    Category::Rvalue(RvalueFunc::Into) => false,
                    _ => true,
                });

                let rvalue = unpack!(block = this.as_rvalue(block, expr));
                this.cfg.push_assign(block, expr_span, destination, rvalue);
                block.unit()
            }
        }
    }

    fn break_or_continue<F>(&mut self,
                            span: Span,
                            label: Option<CodeExtent>,
                            block: BasicBlock,
                            exit_selector: F)
                            -> BlockAnd<()>
        where F: FnOnce(&mut LoopScope) -> BasicBlock
    {
        let (exit_block, extent) = {
            let loop_scope = self.find_loop_scope(span, label);
            (exit_selector(loop_scope), loop_scope.extent)
        };
        self.exit_scope(span, extent, block, exit_block);
        self.cfg.start_new_block().unit()
    }
}
<commit_msg>Auto merge of #31469 - nagisa:mir-else-dest-fix, r=arielb1<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! See docs in build/expr/mod.rs

use build::{BlockAnd, BlockAndExtension, Builder};
use build::expr::category::{Category, RvalueFunc};
use build::scope::LoopScope;
use hair::*;
use rustc::middle::region::CodeExtent;
use rustc::middle::ty;
use rustc::mir::repr::*;
use syntax::codemap::Span;

impl<'a,'tcx> Builder<'a,'tcx> {
    /// Compile `expr`, storing the result into `destination`, which
    /// is assumed to be uninitialized.
    pub fn into_expr(&mut self,
                     destination: &Lvalue<'tcx>,
                     mut block: BasicBlock,
                     expr: Expr<'tcx>)
                     -> BlockAnd<()>
    {
        debug!("into_expr(destination={:?}, block={:?}, expr={:?})",
               destination, block, expr);

        // since we frequently have to reference `self` from within a
        // closure, where `self` would be shadowed, it's easier to
        // just use the name `this` uniformly
        let this = self;
        let expr_span = expr.span;

        match expr.kind {
            ExprKind::Scope { extent, value } => {
                this.in_scope(extent, block, |this| this.into(destination, block, value))
            }
            ExprKind::Block { body: ast_block } => {
                this.ast_block(destination, block, ast_block)
            }
            ExprKind::Match { discriminant, arms } => {
                this.match_expr(destination, expr_span, block, discriminant, arms)
            }
            ExprKind::If { condition: cond_expr, then: then_expr, otherwise: else_expr } => {
                let operand = unpack!(block = this.as_operand(block, cond_expr));

                let mut then_block = this.cfg.start_new_block();
                let mut else_block = this.cfg.start_new_block();
                this.cfg.terminate(block, Terminator::If {
                    cond: operand,
                    targets: (then_block, else_block)
                });

                unpack!(then_block = this.into(destination, then_block, then_expr));
                else_block = if let Some(else_expr) = else_expr {
                    unpack!(this.into(destination, else_block, else_expr))
                } else {
                    // Body of the `if` expression without an `else` clause must return `()`, thus
                    // we implicitly generate a `else {}` if it is not specified.
                    this.cfg.push_assign_unit(else_block, expr_span, destination);
                    else_block
                };

                let join_block = this.cfg.start_new_block();
                this.cfg.terminate(then_block, Terminator::Goto { target: join_block });
                this.cfg.terminate(else_block, Terminator::Goto { target: join_block });

                join_block.unit()
            }
            ExprKind::LogicalOp { op, lhs, rhs } => {
                // And:
                //
                // [block: If(lhs)] -true-> [else_block: If(rhs)] -true-> [true_block]
                //        |                          | (false)
                //        +----------false-----------+------------------> [false_block]
                //
                // Or:
                //
                // [block: If(lhs)] -false-> [else_block: If(rhs)] -true-> [true_block]
                //        |                          | (false)
                //        +----------true------------+-------------------> [false_block]

                let (true_block, false_block, mut else_block, join_block) =
                    (this.cfg.start_new_block(), this.cfg.start_new_block(),
                     this.cfg.start_new_block(), this.cfg.start_new_block());

                let lhs = unpack!(block = this.as_operand(block, lhs));
                let blocks = match op {
                    LogicalOp::And => (else_block, false_block),
                    LogicalOp::Or => (true_block, else_block),
                };
                this.cfg.terminate(block, Terminator::If { cond: lhs, targets: blocks });

                let rhs = unpack!(else_block = this.as_operand(else_block, rhs));
                this.cfg.terminate(else_block, Terminator::If {
                    cond: rhs,
                    targets: (true_block, false_block)
                });

                this.cfg.push_assign_constant(
                    true_block, expr_span, destination,
                    Constant {
                        span: expr_span,
                        ty: this.hir.bool_ty(),
                        literal: this.hir.true_literal(),
                    });

                this.cfg.push_assign_constant(
                    false_block, expr_span, destination,
                    Constant {
                        span: expr_span,
                        ty: this.hir.bool_ty(),
                        literal: this.hir.false_literal(),
                    });

                this.cfg.terminate(true_block, Terminator::Goto { target: join_block });
                this.cfg.terminate(false_block, Terminator::Goto { target: join_block });

                join_block.unit()
            }
            ExprKind::Loop { condition: opt_cond_expr, body } => {
                // [block] --> [loop_block] ~~> [loop_block_end] -1-> [exit_block]
                //                  ^                  |
                //                  |                  0
                //                  |                  |
                //                  |                  v
                //           [body_block_end] <~~~ [body_block]
                //
                // If `opt_cond_expr` is `None`, then the graph is somewhat simplified:
                //
                // [block] --> [loop_block / body_block ] ~~> [body_block_end]    [exit_block]
                //                         ^                          |
                //                         |                          |
                //                         +--------------------------+
                //

                let loop_block = this.cfg.start_new_block();
                let exit_block = this.cfg.start_new_block();

                // start the loop
                this.cfg.terminate(block, Terminator::Goto { target: loop_block });

                let might_break = this.in_loop_scope(loop_block, exit_block, move |this| {
                    // conduct the test, if necessary
                    let body_block;
                    if let Some(cond_expr) = opt_cond_expr {
                        // This loop has a condition, ergo its exit_block is reachable.
                        this.find_loop_scope(expr_span, None).might_break = true;

                        let loop_block_end;
                        let cond = unpack!(loop_block_end = this.as_operand(loop_block, cond_expr));
                        body_block = this.cfg.start_new_block();
                        this.cfg.terminate(loop_block_end,
                                           Terminator::If {
                                               cond: cond,
                                               targets: (body_block, exit_block)
                                           });
                    } else {
                        body_block = loop_block;
                    }

                    // The “return” value of the loop body must always be an unit, but we cannot
                    // reuse that as a “return” value of the whole loop expressions, because some
                    // loops are diverging (e.g. `loop {}`). Thus, we introduce a unit temporary as
                    // the destination for the loop body and assign the loop’s own “return” value
                    // immediately after the iteration is finished.
                    let tmp = this.get_unit_temp();
                    // Execute the body, branching back to the test.
                    let body_block_end = unpack!(this.into(&tmp, body_block, body));
                    this.cfg.terminate(body_block_end, Terminator::Goto { target: loop_block });
                });
                // If the loop may reach its exit_block, we assign an empty tuple to the
                // destination to keep the MIR well-formed.
                if might_break {
                    this.cfg.push_assign_unit(exit_block, expr_span, destination);
                }
                exit_block.unit()
            }
            ExprKind::Assign { lhs, rhs } => {
                // Note: we evaluate assignments right-to-left. This
                // is better for borrowck interaction with overloaded
                // operators like x[j] = x[i].
                let rhs = unpack!(block = this.as_operand(block, rhs));
                let lhs = unpack!(block = this.as_lvalue(block, lhs));
                unpack!(block = this.build_drop(block, lhs.clone()));
                this.cfg.push_assign(block, expr_span, &lhs, Rvalue::Use(rhs));
                block.unit()
            }
            ExprKind::AssignOp { op, lhs, rhs } => {
                // FIXME(#28160) there is an interesting semantics
                // question raised here -- should we "freeze" the
                // value of the lhs here?  I'm inclined to think not,
                // since it seems closer to the semantics of the
                // overloaded version, which takes `&mut self`.  This
                // only affects weird things like `x += {x += 1; x}`
                // -- is that equal to `x + (x + 1)` or `2*(x+1)`?

                // As above, RTL.
                let rhs = unpack!(block = this.as_operand(block, rhs));
                let lhs = unpack!(block = this.as_lvalue(block, lhs));

                // we don't have to drop prior contents or anything
                // because AssignOp is only legal for Copy types
                // (overloaded ops should be desugared into a call).
                this.cfg.push_assign(block, expr_span, &lhs,
                                     Rvalue::BinaryOp(op,
                                                      Operand::Consume(lhs.clone()),
                                                      rhs));

                block.unit()
            }
            ExprKind::Continue { label } => {
                this.break_or_continue(expr_span, label, block,
                                       |loop_scope| loop_scope.continue_block)
            }
            ExprKind::Break { label } => {
                this.break_or_continue(expr_span, label, block, |loop_scope| {
                    loop_scope.might_break = true;
                    loop_scope.break_block
                })
            }
            ExprKind::Return { value } => {
                block = match value {
                    Some(value) => unpack!(this.into(&Lvalue::ReturnPointer, block, value)),
                    None => {
                        this.cfg.push_assign_unit(block, expr_span, &Lvalue::ReturnPointer);
                        block
                    }
                };
                let extent = this.extent_of_outermost_scope();
                this.exit_scope(expr_span, extent, block, END_BLOCK);
                this.cfg.start_new_block().unit()
            }
            ExprKind::Call { ty, fun, args } => {
                let diverges = match ty.sty {
                    ty::TyBareFn(_, ref f) => f.sig.0.output.diverges(),
                    _ => false
                };
                let fun = unpack!(block = this.as_operand(block, fun));
                let args: Vec<_> =
                    args.into_iter()
                        .map(|arg| unpack!(block = this.as_operand(block, arg)))
                        .collect();

                let success = this.cfg.start_new_block();
                let cleanup = this.diverge_cleanup();
                this.cfg.terminate(block, Terminator::Call {
                    func: fun,
                    args: args,
                    cleanup: cleanup,
                    destination: if diverges {
                        None
                    } else {
                        Some ((destination.clone(), success))
                    }
                });
                success.unit()
            }

            // these are the cases that are more naturally handled by some other mode
            ExprKind::Unary { .. } |
            ExprKind::Binary { .. } |
            ExprKind::Box { .. } |
            ExprKind::Cast { .. } |
            ExprKind::ReifyFnPointer { .. } |
            ExprKind::UnsafeFnPointer { .. } |
            ExprKind::Unsize { .. } |
            ExprKind::Repeat { .. } |
            ExprKind::Borrow { .. } |
            ExprKind::VarRef { .. } |
            ExprKind::SelfRef |
            ExprKind::StaticRef { .. } |
            ExprKind::Vec { .. } |
            ExprKind::Tuple { .. } |
            ExprKind::Adt { .. } |
            ExprKind::Closure { .. } |
            ExprKind::Index { .. } |
            ExprKind::Deref { .. } |
            ExprKind::Literal { .. } |
            ExprKind::InlineAsm { .. } |
            ExprKind::Field { .. } => {
                debug_assert!(match Category::of(&expr.kind).unwrap() {
                    Category::Rvalue(RvalueFunc::Into) => false,
                    _ => true,
                });

                let rvalue = unpack!(block = this.as_rvalue(block, expr));
                this.cfg.push_assign(block, expr_span, destination, rvalue);
                block.unit()
            }
        }
    }

    fn break_or_continue<F>(&mut self,
                            span: Span,
                            label: Option<CodeExtent>,
                            block: BasicBlock,
                            exit_selector: F)
                            -> BlockAnd<()>
        where F: FnOnce(&mut LoopScope) -> BasicBlock
    {
        let (exit_block, extent) = {
            let loop_scope = self.find_loop_scope(span, label);
            (exit_selector(loop_scope), loop_scope.extent)
        };
        self.exit_scope(span, extent, block, exit_block);
        self.cfg.start_new_block().unit()
    }
}
<|endoftext|>


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

#![feature(decl_macro)]

pub macro create_struct($a:ident) {
    struct $a;
    impl Clone for $a {
        fn clone(&self) -> Self {
            $a
        }
    }
}

fn main() {
    create_struct!(Test);
    Test.clone();
}
<|endoftext|>


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

#![allow(dead_code, unused_variables)]
#![feature(box_heap)]
#![feature(placement_in_syntax)]

// Tests that the new `in` syntax works with unique pointers.
//
// Compare with new-box-syntax.rs

use std::boxed::{Box, HEAP};

struct Structure {
    x: isize,
    y: isize,
}

pub fn main() {
    let x: Box<isize> = in HEAP { 2 };
    let b: Box<isize> = in HEAP { 1 + 2 };
    let c = in HEAP { 3 + 4 };

    let s: Box<Structure> = in HEAP {
        Structure {
            x: 3,
            y: 4,
        }
    };
}
<|endoftext|>


<commit_before><commit_msg>niko example<commit_after>#[macro_use]
extern crate abomonation_derive;
extern crate abomonation;

extern crate rand;
extern crate timely;
extern crate graph_map;
extern crate differential_dataflow;

use timely::dataflow::*;

use differential_dataflow::input::Input;
use differential_dataflow::operators::*;

// Types whose definitions I don't actually know.
#[derive(Ord,PartialOrd,Eq,PartialEq,Clone,Copy,Abomonation,Debug,Hash)]
struct Region(usize);
#[derive(Ord,PartialOrd,Eq,PartialEq,Clone,Copy,Abomonation,Debug,Hash)]
struct Borrow(usize);
#[derive(Ord,PartialOrd,Eq,PartialEq,Clone,Copy,Abomonation,Debug,Hash)]
struct Point(usize);
// apparently unused?
#[derive(Ord,PartialOrd,Eq,PartialEq,Clone,Copy,Abomonation,Debug,Hash)]
enum EdgeKind { Inter, Intra }

fn main() {

    timely::execute_from_args(std::env::args().skip(1), move |worker| {

        let mut probe = ProbeHandle::new();

        let mut inputs = worker.dataflow::<(),_,_>(|scope| {

            // inputs to the computation
            let (input_1, borrow_region) = scope.new_collection::<(Region,Borrow,Point),isize>();
            let (input_2, next_statement) = scope.new_collection::<(Point,Point),isize>();
            let (input_3, goto) = scope.new_collection::<(Point,Point),isize>();
            let (input_4, rloets) = scope.new_collection::<(Region,Point),isize>();
            let (input_5, killed) = scope.new_collection::<(Borrow,Point),isize>();
            let (input_6, out_lives) = scope.new_collection::<(Region,Region,Point),isize>();

            // `cfg_edge` contains pairs (P, Q)
            let cfg_edge =
            next_statement
                .concat(&goto)
                .distinct()
                .probe_with(&mut probe);

            // `region_live_at` contains pairs (R, P)
            let region_live_at_1 = rloets.clone();
            let region_live_at_2 = goto.map(|(p,q)| (q,p))
                                       .join_map(&rloets.map(|(r,q)| (q,r)), |_q,&p,&r| (r,p));
            let region_live_at =
            region_live_at_1
                .concat(&region_live_at_2)
                .distinct()
                .probe_with(&mut probe);

            // `points_to` contains triples (R, B, P)
            let points_to =
            borrow_region
                .iterate(|points_to| {

                    // rule 1: base case.
                    let mut result = borrow_region.enter(&points_to.scope());

                    // rule 2: result + whatever from this rule.
                    result =
                    points_to
                        .map(|(r2,b,p)| ((b,p),r2))
                        .antijoin(&killed.enter(&points_to.scope()))
                        .map(|((b,p),r2)| ((r2,p),b))
                        .join(&out_lives.enter(&points_to.scope()).map(|(r2,r1,p)| ((r2,p),r1)))
                        .map(|((_r2,p),b,r1)| (p,(b,r1)))
                        .join(&next_statement.enter(&points_to.scope()))
                        .map(|(_p,(b,r1),q)| (r1,b,q))
                        .concat(&result);

                    // rule 3: result + whatever from this rule.
                    result =
                    points_to
                        .map(|(r1,b,p)| ((b,p),r1))
                        .antijoin(&killed.enter(&points_to.scope()))
                        .map(|((b,p),r1)| (p,(b,r1)))
                        .join(&next_statement.enter(&points_to.scope()))
                        .map(|(p,(b,r1),q)| ((r1,q),(b,p)))
                        .semijoin(&region_live_at.enter(&points_to.scope()))
                        .map(|((r1,q),(b,_p))| (r1,b,q))
                        .concat(&result);

                    result.distinct()
                })
                .probe_with(&mut probe);

            let borrow_live_at =
            points_to
                .map(|(r,b,p)| ((r,p),b))
                .semijoin(&region_live_at)
                .probe_with(&mut probe);

            (input_1, input_2, input_3, input_4, input_5, input_6)
        });

    }).unwrap();
}
<|endoftext|>