<commit_before>//! Source map for translating source entity names to parsed entities.
//!
//! When the parser reads in a source file, entities like instructions, EBBs, and values get new
//! entity numbers. The parser maintains a mapping from the entity names in the source to the final
//! entity references.
//!
//! The `SourceMap` struct defined in this module makes the same mapping available to parser
//! clients.

use std::collections::HashMap;
use cretonne::ir::{StackSlot, JumpTable, Ebb, Value};
use cretonne::ir::entities::AnyEntity;
use error::{Result, Location};
use lexer::split_entity_name;

/// Mapping from source entity names to entity references that are valid in the parsed function.
#[derive(Debug)]
pub struct SourceMap {
    values: HashMap<Value, Value>, // vNN, vxNN
    ebbs: HashMap<Ebb, Ebb>, // ebbNN
    stack_slots: HashMap<u32, StackSlot>, // ssNN
    jump_tables: HashMap<u32, JumpTable>, // jtNN

    // Store locations for entities, including instructions.
    locations: HashMap<AnyEntity, Location>,
}

/// Read-only interface which is exposed outside the parser crate.
impl SourceMap {
    /// Look up a value entity by its source number.
    pub fn get_value(&self, src: Value) -> Option<Value> {
        self.values.get(&src).cloned()
    }

    /// Look up a EBB entity by its source number.
    pub fn get_ebb(&self, src: Ebb) -> Option<Ebb> {
        self.ebbs.get(&src).cloned()
    }

    /// Look up a stack slot entity by its source number.
    pub fn get_ss(&self, src_num: u32) -> Option<StackSlot> {
        self.stack_slots.get(&src_num).cloned()
    }

    /// Look up a jump table entity by its source number.
    pub fn get_jt(&self, src_num: u32) -> Option<JumpTable> {
        self.jump_tables.get(&src_num).cloned()
    }

    /// Look up an entity by source name.
    /// Returns the entity reference corresponding to `name`, if it exists.
    pub fn lookup_str(&self, name: &str) -> Option<AnyEntity> {
        split_entity_name(name).and_then(|(ent, num)| {
            match ent {
                "v" => {
                    Value::direct_with_number(num)
                        .and_then(|v| self.get_value(v))
                        .map(AnyEntity::Value)
                }
                "vx" => {
                    Value::table_with_number(num)
                        .and_then(|v| self.get_value(v))
                        .map(AnyEntity::Value)
                }
                "ebb" => Ebb::with_number(num).and_then(|e| self.get_ebb(e)).map(AnyEntity::Ebb),
                "ss" => self.get_ss(num).map(AnyEntity::StackSlot),
                "jt" => self.get_jt(num).map(AnyEntity::JumpTable),
                _ => None,
            }
        })
    }

    /// Get the source location where an entity was defined.
    /// This looks up entities in the parsed function, not the source entity numbers.
    pub fn location(&self, entity: AnyEntity) -> Option<Location> {
        self.locations.get(&entity).cloned()
    }

    /// Rewrite an Ebb reference.
    pub fn rewrite_ebb(&self, ebb: &mut Ebb, loc: AnyEntity) -> Result<()> {
        match self.get_ebb(*ebb) {
            Some(new) => {
                *ebb = new;
                Ok(())
            }
            None => {
                err!(self.location(loc).unwrap_or_default(),
                     "undefined reference: {}",
                     ebb)
            }
        }
    }

    /// Rewrite a value reference.
    pub fn rewrite_value(&self, val: &mut Value, loc: AnyEntity) -> Result<()> {
        match self.get_value(*val) {
            Some(new) => {
                *val = new;
                Ok(())
            }
            None => {
                err!(self.location(loc).unwrap_or_default(),
                     "undefined reference: {}",
                     val)
            }
        }
    }

    /// Rewrite a slice of value references.
    pub fn rewrite_values(&self, vals: &mut [Value], loc: AnyEntity) -> Result<()> {
        for val in vals {
            try!(self.rewrite_value(val, loc));
        }
        Ok(())
    }
}

/// Interface for mutating a source map.
///
/// This interface is provided for the parser itself, it is not made available outside the crate.
pub trait MutableSourceMap {
    fn new() -> Self;

    /// Define a value mapping from the source name `src` to the final `entity`.
    fn def_value(&mut self, src: Value, entity: Value, loc: &Location) -> Result<()>;
    fn def_ebb(&mut self, src: Ebb, entity: Ebb, loc: &Location) -> Result<()>;
    fn def_ss(&mut self, src_num: u32, entity: StackSlot, loc: &Location) -> Result<()>;
    fn def_jt(&mut self, src_num: u32, entity: JumpTable, loc: &Location) -> Result<()>;

    /// Define an entity without an associated source number. This can be used for instructions
    /// whose numbers never appear in source, or implicitly defined signatures.
    fn def_entity(&mut self, entity: AnyEntity, loc: &Location) -> Result<()>;
}

impl MutableSourceMap for SourceMap {
    fn new() -> SourceMap {
        SourceMap {
            values: HashMap::new(),
            ebbs: HashMap::new(),
            stack_slots: HashMap::new(),
            jump_tables: HashMap::new(),
            locations: HashMap::new(),
        }
    }

    fn def_value(&mut self, src: Value, entity: Value, loc: &Location) -> Result<()> {
        if self.values.insert(src, entity).is_some() {
            err!(loc, "duplicate value: {}", src)
        } else {
            self.def_entity(entity.into(), loc)
        }
    }

    fn def_ebb(&mut self, src: Ebb, entity: Ebb, loc: &Location) -> Result<()> {
        if self.ebbs.insert(src, entity).is_some() {
            err!(loc, "duplicate EBB: {}", src)
        } else {
            self.def_entity(entity.into(), loc)
        }
    }

    fn def_ss(&mut self, src_num: u32, entity: StackSlot, loc: &Location) -> Result<()> {
        if self.stack_slots.insert(src_num, entity).is_some() {
            err!(loc, "duplicate stack slot: ss{}", src_num)
        } else {
            self.def_entity(entity.into(), loc)
        }
    }

    fn def_jt(&mut self, src_num: u32, entity: JumpTable, loc: &Location) -> Result<()> {
        if self.jump_tables.insert(src_num, entity).is_some() {
            err!(loc, "duplicate jump table: jt{}", src_num)
        } else {
            self.def_entity(entity.into(), loc)
        }
    }

    fn def_entity(&mut self, entity: AnyEntity, loc: &Location) -> Result<()> {
        if self.locations.insert(entity, loc.clone()).is_some() {
            err!(loc, "duplicate entity: {}", entity)
        } else {
            Ok(())
        }
    }
}

#[cfg(test)]
mod tests {
    use parse_test;

    #[test]
    fn details() {
        let tf = parse_test("function detail() {
                               ss10 = stack_slot 13
                               jt10 = jump_table ebb0
                             ebb0(v4: i32, vx7: i32):
                               v10 = iadd v4, vx7
                             }")
            .unwrap();
        let map = &tf.functions[0].1.map;

        assert_eq!(map.lookup_str("v0"), None);
        assert_eq!(map.lookup_str("ss1"), None);
        assert_eq!(map.lookup_str("ss10").unwrap().to_string(), "ss0");
        assert_eq!(map.lookup_str("jt10").unwrap().to_string(), "jt0");
        assert_eq!(map.lookup_str("ebb0").unwrap().to_string(), "ebb0");
        assert_eq!(map.lookup_str("v4").unwrap().to_string(), "vx0");
        assert_eq!(map.lookup_str("vx7").unwrap().to_string(), "vx1");
        assert_eq!(map.lookup_str("v10").unwrap().to_string(), "v0");
    }
}
<commit_msg>Track signatures and function references in the source map.<commit_after>//! Source map for translating source entity names to parsed entities.
//!
//! When the parser reads in a source file, entities like instructions, EBBs, and values get new
//! entity numbers. The parser maintains a mapping from the entity names in the source to the final
//! entity references.
//!
//! The `SourceMap` struct defined in this module makes the same mapping available to parser
//! clients.

use std::collections::HashMap;
use cretonne::ir::{StackSlot, JumpTable, Ebb, Value, SigRef, FuncRef};
use cretonne::ir::entities::AnyEntity;
use error::{Result, Location};
use lexer::split_entity_name;

/// Mapping from source entity names to entity references that are valid in the parsed function.
#[derive(Debug)]
pub struct SourceMap {
    values: HashMap<Value, Value>, // vNN, vxNN
    ebbs: HashMap<Ebb, Ebb>, // ebbNN
    stack_slots: HashMap<u32, StackSlot>, // ssNN
    signatures: HashMap<u32, SigRef>, // sigNN
    functions: HashMap<u32, FuncRef>, // fnNN
    jump_tables: HashMap<u32, JumpTable>, // jtNN

    // Store locations for entities, including instructions.
    locations: HashMap<AnyEntity, Location>,
}

/// Read-only interface which is exposed outside the parser crate.
impl SourceMap {
    /// Look up a value entity by its source number.
    pub fn get_value(&self, src: Value) -> Option<Value> {
        self.values.get(&src).cloned()
    }

    /// Look up a EBB entity by its source number.
    pub fn get_ebb(&self, src: Ebb) -> Option<Ebb> {
        self.ebbs.get(&src).cloned()
    }

    /// Look up a stack slot entity by its source number.
    pub fn get_ss(&self, src_num: u32) -> Option<StackSlot> {
        self.stack_slots.get(&src_num).cloned()
    }

    /// Look up a signature entity by its source number.
    pub fn get_sig(&self, src_num: u32) -> Option<SigRef> {
        self.signatures.get(&src_num).cloned()
    }

    /// Look up a function entity by its source number.
    pub fn get_fn(&self, src_num: u32) -> Option<FuncRef> {
        self.functions.get(&src_num).cloned()
    }

    /// Look up a jump table entity by its source number.
    pub fn get_jt(&self, src_num: u32) -> Option<JumpTable> {
        self.jump_tables.get(&src_num).cloned()
    }

    /// Look up an entity by source name.
    /// Returns the entity reference corresponding to `name`, if it exists.
    pub fn lookup_str(&self, name: &str) -> Option<AnyEntity> {
        split_entity_name(name).and_then(|(ent, num)| {
            match ent {
                "v" => {
                    Value::direct_with_number(num)
                        .and_then(|v| self.get_value(v))
                        .map(AnyEntity::Value)
                }
                "vx" => {
                    Value::table_with_number(num)
                        .and_then(|v| self.get_value(v))
                        .map(AnyEntity::Value)
                }
                "ebb" => Ebb::with_number(num).and_then(|e| self.get_ebb(e)).map(AnyEntity::Ebb),
                "ss" => self.get_ss(num).map(AnyEntity::StackSlot),
                "sig" => self.get_sig(num).map(AnyEntity::SigRef),
                "fn" => self.get_fn(num).map(AnyEntity::FuncRef),
                "jt" => self.get_jt(num).map(AnyEntity::JumpTable),
                _ => None,
            }
        })
    }

    /// Get the source location where an entity was defined.
    /// This looks up entities in the parsed function, not the source entity numbers.
    pub fn location(&self, entity: AnyEntity) -> Option<Location> {
        self.locations.get(&entity).cloned()
    }

    /// Rewrite an Ebb reference.
    pub fn rewrite_ebb(&self, ebb: &mut Ebb, loc: AnyEntity) -> Result<()> {
        match self.get_ebb(*ebb) {
            Some(new) => {
                *ebb = new;
                Ok(())
            }
            None => {
                err!(self.location(loc).unwrap_or_default(),
                     "undefined reference: {}",
                     ebb)
            }
        }
    }

    /// Rewrite a value reference.
    pub fn rewrite_value(&self, val: &mut Value, loc: AnyEntity) -> Result<()> {
        match self.get_value(*val) {
            Some(new) => {
                *val = new;
                Ok(())
            }
            None => {
                err!(self.location(loc).unwrap_or_default(),
                     "undefined reference: {}",
                     val)
            }
        }
    }

    /// Rewrite a slice of value references.
    pub fn rewrite_values(&self, vals: &mut [Value], loc: AnyEntity) -> Result<()> {
        for val in vals {
            try!(self.rewrite_value(val, loc));
        }
        Ok(())
    }
}

/// Interface for mutating a source map.
///
/// This interface is provided for the parser itself, it is not made available outside the crate.
pub trait MutableSourceMap {
    fn new() -> Self;

    /// Define a value mapping from the source name `src` to the final `entity`.
    fn def_value(&mut self, src: Value, entity: Value, loc: &Location) -> Result<()>;
    fn def_ebb(&mut self, src: Ebb, entity: Ebb, loc: &Location) -> Result<()>;
    fn def_ss(&mut self, src_num: u32, entity: StackSlot, loc: &Location) -> Result<()>;
    fn def_sig(&mut self, src_num: u32, entity: SigRef, loc: &Location) -> Result<()>;
    fn def_fn(&mut self, src_num: u32, entity: FuncRef, loc: &Location) -> Result<()>;
    fn def_jt(&mut self, src_num: u32, entity: JumpTable, loc: &Location) -> Result<()>;

    /// Define an entity without an associated source number. This can be used for instructions
    /// whose numbers never appear in source, or implicitly defined signatures.
    fn def_entity(&mut self, entity: AnyEntity, loc: &Location) -> Result<()>;
}

impl MutableSourceMap for SourceMap {
    fn new() -> SourceMap {
        SourceMap {
            values: HashMap::new(),
            ebbs: HashMap::new(),
            stack_slots: HashMap::new(),
            signatures: HashMap::new(),
            functions: HashMap::new(),
            jump_tables: HashMap::new(),
            locations: HashMap::new(),
        }
    }

    fn def_value(&mut self, src: Value, entity: Value, loc: &Location) -> Result<()> {
        if self.values.insert(src, entity).is_some() {
            err!(loc, "duplicate value: {}", src)
        } else {
            self.def_entity(entity.into(), loc)
        }
    }

    fn def_ebb(&mut self, src: Ebb, entity: Ebb, loc: &Location) -> Result<()> {
        if self.ebbs.insert(src, entity).is_some() {
            err!(loc, "duplicate EBB: {}", src)
        } else {
            self.def_entity(entity.into(), loc)
        }
    }

    fn def_ss(&mut self, src_num: u32, entity: StackSlot, loc: &Location) -> Result<()> {
        if self.stack_slots.insert(src_num, entity).is_some() {
            err!(loc, "duplicate stack slot: ss{}", src_num)
        } else {
            self.def_entity(entity.into(), loc)
        }
    }

    fn def_sig(&mut self, src_num: u32, entity: SigRef, loc: &Location) -> Result<()> {
        if self.signatures.insert(src_num, entity).is_some() {
            err!(loc, "duplicate signature: sig{}", src_num)
        } else {
            self.def_entity(entity.into(), loc)
        }
    }

    fn def_fn(&mut self, src_num: u32, entity: FuncRef, loc: &Location) -> Result<()> {
        if self.functions.insert(src_num, entity).is_some() {
            err!(loc, "duplicate function: fn{}", src_num)
        } else {
            self.def_entity(entity.into(), loc)
        }
    }

    fn def_jt(&mut self, src_num: u32, entity: JumpTable, loc: &Location) -> Result<()> {
        if self.jump_tables.insert(src_num, entity).is_some() {
            err!(loc, "duplicate jump table: jt{}", src_num)
        } else {
            self.def_entity(entity.into(), loc)
        }
    }

    fn def_entity(&mut self, entity: AnyEntity, loc: &Location) -> Result<()> {
        if self.locations.insert(entity, loc.clone()).is_some() {
            err!(loc, "duplicate entity: {}", entity)
        } else {
            Ok(())
        }
    }
}

#[cfg(test)]
mod tests {
    use parse_test;

    #[test]
    fn details() {
        let tf = parse_test("function detail() {
                               ss10 = stack_slot 13
                               jt10 = jump_table ebb0
                             ebb0(v4: i32, vx7: i32):
                               v10 = iadd v4, vx7
                             }")
            .unwrap();
        let map = &tf.functions[0].1.map;

        assert_eq!(map.lookup_str("v0"), None);
        assert_eq!(map.lookup_str("ss1"), None);
        assert_eq!(map.lookup_str("ss10").unwrap().to_string(), "ss0");
        assert_eq!(map.lookup_str("jt10").unwrap().to_string(), "jt0");
        assert_eq!(map.lookup_str("ebb0").unwrap().to_string(), "ebb0");
        assert_eq!(map.lookup_str("v4").unwrap().to_string(), "vx0");
        assert_eq!(map.lookup_str("vx7").unwrap().to_string(), "vx1");
        assert_eq!(map.lookup_str("v10").unwrap().to_string(), "v0");
    }
}
<|endoftext|>


<commit_before>extern crate futures;

use std::sync::mpsc::channel;
use std::thread;

use futures::*;

#[test]
fn and_then1() {
    let (tx, rx) = channel();

    let tx2 = tx.clone();
    let p1 = finished::<_, i32>("a").then(move |t| { tx2.send("first").unwrap(); t });
    let tx2 = tx.clone();
    let p2 = finished("b").then(move |t| { tx2.send("second").unwrap(); t });
    let f = p1.and_then(|_| p2);

    assert!(rx.try_recv().is_err());
    f.map(move |s| tx.send(s).unwrap()).forget();
    assert_eq!(rx.recv(), Ok("first"));
    assert_eq!(rx.recv(), Ok("second"));
    assert_eq!(rx.recv(), Ok("b"));
    assert!(rx.recv().is_err());
}

#[test]
fn and_then2() {
    let (tx, rx) = channel();

    let tx2 = tx.clone();
    let p1 = failed::<i32, _>(2).then(move |t| { tx2.send("first").unwrap(); t });
    let tx2 = tx.clone();
    let p2 = finished("b").then(move |t| { tx2.send("second").unwrap(); t });
    let f = p1.and_then(|_| p2);

    assert!(rx.try_recv().is_err());
    f.map_err(|_| drop(tx)).forget();
    assert_eq!(rx.recv(), Ok("first"));
    assert!(rx.recv().is_err());
}

#[test]
fn oneshot1() {
    let (c, p) = oneshot::<i32>();
    let t = thread::spawn(|| c.complete(1));

    let (tx, rx) = channel();
    p.map(move |e| tx.send(e).unwrap()).forget();
    assert_eq!(rx.recv(), Ok(1));
    t.join().unwrap();
}

#[test]
fn oneshot2() {
    let (c, p) = oneshot::<i32>();
    let t = thread::spawn(|| c.complete(1));
    t.join().unwrap();

    let (tx, rx) = channel();
    p.map(move |e| tx.send(e).unwrap()).forget();
    assert_eq!(rx.recv(), Ok(1));
}

#[test]
fn oneshot3() {
    let (c, p) = oneshot::<i32>();
    let (tx, rx) = channel();
    p.map(move |e| tx.send(e).unwrap()).forget();

    let t = thread::spawn(|| c.complete(1));
    t.join().unwrap();

    assert_eq!(rx.recv(), Ok(1));
}

#[test]
fn oneshot4() {
    let (c, p) = oneshot::<i32>();
    drop(c);

    let (tx, rx) = channel();
    p.map(move |e| tx.send(e).unwrap()).forget();
    assert!(rx.recv().is_err());
}

#[test]
fn proimse5() {
    let (c, p) = oneshot::<i32>();
    drop(p);
    c.complete(2);
}

#[test]
fn oneshot5() {
    let (c, p) = oneshot::<i32>();
    let t = thread::spawn(|| drop(c));
    let (tx, rx) = channel();
    p.map(move |t| tx.send(t).unwrap()).forget();
    t.join().unwrap();
    assert!(rx.recv().is_err());
}

#[test]
fn cancel1() {
    let (c, p) = oneshot::<i32>();
    drop(c);
    p.map(|_| panic!()).forget();
}

#[test]
fn map_err1() {
    finished::<i32, i32>(1).map_err(|_| panic!()).forget();
}

#[test]
fn map_err2() {
    let (tx, rx) = channel();
    failed::<i32, i32>(1).map_err(move |v| tx.send(v).unwrap()).forget();
    assert_eq!(rx.recv(), Ok(1));
    assert!(rx.recv().is_err());
}

#[test]
fn map_err3() {
    let (c, p) = oneshot::<i32>();
    p.map_err(|_| {}).forget();
    drop(c);
}

#[test]
fn or_else1() {
    let (c1, p1) = oneshot::<i32>();
    let (c2, p2) = oneshot::<i32>();

    let (tx, rx) = channel();
    let tx2 = tx.clone();
    let p1 = p1.map_err(move |i| { tx2.send(2).unwrap(); i });
    let tx2 = tx.clone();
    let p2 = p2.map(move |i| { tx2.send(i).unwrap(); i });

    assert!(rx.try_recv().is_err());
    drop(c1);
    c2.complete(3);
    p1.or_else(|_| p2).map(move |v| tx.send(v).unwrap()).forget();

    assert_eq!(rx.recv(), Ok(2));
    assert_eq!(rx.recv(), Ok(3));
    assert_eq!(rx.recv(), Ok(3));
    assert!(rx.recv().is_err());
}

#[test]
fn or_else2() {
    let (c1, p1) = oneshot::<i32>();

    let (tx, rx) = channel();

    p1.or_else(move |_| {
        tx.send(()).unwrap();
        finished::<i32, i32>(1)
    }).forget();

    c1.complete(2);
    assert!(rx.recv().is_err());
}

#[test]
fn join1() {
    let (tx, rx) = channel();
    finished::<i32, i32>(1).join(finished(2))
                           .map(move |v| tx.send(v).unwrap())
                           .forget();
    assert_eq!(rx.recv(), Ok((1, 2)));
    assert!(rx.recv().is_err());
}

#[test]
fn join2() {
    let (c1, p1) = oneshot::<i32>();
    let (c2, p2) = oneshot::<i32>();
    let (tx, rx) = channel();
    p1.join(p2).map(move |v| tx.send(v).unwrap()).forget();
    assert!(rx.try_recv().is_err());
    c1.complete(1);
    assert!(rx.try_recv().is_err());
    c2.complete(2);
    assert_eq!(rx.recv(), Ok((1, 2)));
    assert!(rx.recv().is_err());
}

#[test]
fn join3() {
    let (c1, p1) = oneshot::<i32>();
    let (c2, p2) = oneshot::<i32>();
    let (tx, rx) = channel();
    p1.join(p2).map_err(move |_v| tx.send(1).unwrap()).forget();
    assert!(rx.try_recv().is_err());
    drop(c1);
    assert_eq!(rx.recv(), Ok(1));
    assert!(rx.recv().is_err());
    drop(c2);
}

#[test]
fn join4() {
    let (c1, p1) = oneshot::<i32>();
    let (c2, p2) = oneshot::<i32>();
    let (tx, rx) = channel();
    p1.join(p2).map_err(move |v| tx.send(v).unwrap()).forget();
    assert!(rx.try_recv().is_err());
    drop(c1);
    assert!(rx.recv().is_ok());
    drop(c2);
    assert!(rx.recv().is_err());
}

#[test]
fn join5() {
    let (c1, p1) = oneshot::<i32>();
    let (c2, p2) = oneshot::<i32>();
    let (c3, p3) = oneshot::<i32>();
    let (tx, rx) = channel();
    p1.join(p2).join(p3).map(move |v| tx.send(v).unwrap()).forget();
    assert!(rx.try_recv().is_err());
    c1.complete(1);
    assert!(rx.try_recv().is_err());
    c2.complete(2);
    assert!(rx.try_recv().is_err());
    c3.complete(3);
    assert_eq!(rx.recv(), Ok(((1, 2), 3)));
    assert!(rx.recv().is_err());
}

#[test]
fn select1() {
    let (c1, p1) = oneshot::<i32>();
    let (c2, p2) = oneshot::<i32>();
    let (tx, rx) = channel();
    p1.select(p2).map(move |v| tx.send(v).unwrap()).forget();
    assert!(rx.try_recv().is_err());
    c1.complete(1);
    let (v, p2) = rx.recv().unwrap();
    assert_eq!(v, 1);
    assert!(rx.recv().is_err());

    let (tx, rx) = channel();
    p2.map(move |v| tx.send(v).unwrap()).forget();
    c2.complete(2);
    assert_eq!(rx.recv(), Ok(2));
    assert!(rx.recv().is_err());
}

#[test]
fn select2() {
    let (c1, p1) = oneshot::<i32>();
    let (c2, p2) = oneshot::<i32>();
    let (tx, rx) = channel();
    p1.select(p2).map_err(move |v| tx.send((1, v.1)).unwrap()).forget();
    assert!(rx.try_recv().is_err());
    drop(c1);
    let (v, p2) = rx.recv().unwrap();
    assert_eq!(v, 1);
    assert!(rx.recv().is_err());

    let (tx, rx) = channel();
    p2.map(move |v| tx.send(v).unwrap()).forget();
    c2.complete(2);
    assert_eq!(rx.recv(), Ok(2));
    assert!(rx.recv().is_err());
}

#[test]
fn select3() {
    let (c1, p1) = oneshot::<i32>();
    let (c2, p2) = oneshot::<i32>();
    let (tx, rx) = channel();
    p1.select(p2).map_err(move |v| tx.send((1, v.1)).unwrap()).forget();
    assert!(rx.try_recv().is_err());
    drop(c1);
    let (v, p2) = rx.recv().unwrap();
    assert_eq!(v, 1);
    assert!(rx.recv().is_err());

    let (tx, rx) = channel();
    p2.map_err(move |_v| tx.send(2).unwrap()).forget();
    drop(c2);
    assert_eq!(rx.recv(), Ok(2));
    assert!(rx.recv().is_err());
}

#[test]
fn select4() {
    let (tx, rx) = channel::<Complete<i32>>();

    let t = thread::spawn(move || {
        for c in rx {
            c.complete(1);
        }
    });

    let (tx2, rx2) = channel();
    for _ in 0..10000 {
        let (c1, p1) = oneshot::<i32>();
        let (c2, p2) = oneshot::<i32>();

        let tx3 = tx2.clone();
        p1.select(p2).map(move |_| tx3.send(()).unwrap()).forget();
        tx.send(c1).unwrap();
        rx2.recv().unwrap();
        drop(c2);
    }
    drop(tx);

    t.join().unwrap();
}
<commit_msg>Typo fix<commit_after>extern crate futures;

use std::sync::mpsc::channel;
use std::thread;

use futures::*;

#[test]
fn and_then1() {
    let (tx, rx) = channel();

    let tx2 = tx.clone();
    let p1 = finished::<_, i32>("a").then(move |t| { tx2.send("first").unwrap(); t });
    let tx2 = tx.clone();
    let p2 = finished("b").then(move |t| { tx2.send("second").unwrap(); t });
    let f = p1.and_then(|_| p2);

    assert!(rx.try_recv().is_err());
    f.map(move |s| tx.send(s).unwrap()).forget();
    assert_eq!(rx.recv(), Ok("first"));
    assert_eq!(rx.recv(), Ok("second"));
    assert_eq!(rx.recv(), Ok("b"));
    assert!(rx.recv().is_err());
}

#[test]
fn and_then2() {
    let (tx, rx) = channel();

    let tx2 = tx.clone();
    let p1 = failed::<i32, _>(2).then(move |t| { tx2.send("first").unwrap(); t });
    let tx2 = tx.clone();
    let p2 = finished("b").then(move |t| { tx2.send("second").unwrap(); t });
    let f = p1.and_then(|_| p2);

    assert!(rx.try_recv().is_err());
    f.map_err(|_| drop(tx)).forget();
    assert_eq!(rx.recv(), Ok("first"));
    assert!(rx.recv().is_err());
}

#[test]
fn oneshot1() {
    let (c, p) = oneshot::<i32>();
    let t = thread::spawn(|| c.complete(1));

    let (tx, rx) = channel();
    p.map(move |e| tx.send(e).unwrap()).forget();
    assert_eq!(rx.recv(), Ok(1));
    t.join().unwrap();
}

#[test]
fn oneshot2() {
    let (c, p) = oneshot::<i32>();
    let t = thread::spawn(|| c.complete(1));
    t.join().unwrap();

    let (tx, rx) = channel();
    p.map(move |e| tx.send(e).unwrap()).forget();
    assert_eq!(rx.recv(), Ok(1));
}

#[test]
fn oneshot3() {
    let (c, p) = oneshot::<i32>();
    let (tx, rx) = channel();
    p.map(move |e| tx.send(e).unwrap()).forget();

    let t = thread::spawn(|| c.complete(1));
    t.join().unwrap();

    assert_eq!(rx.recv(), Ok(1));
}

#[test]
fn oneshot4() {
    let (c, p) = oneshot::<i32>();
    drop(c);

    let (tx, rx) = channel();
    p.map(move |e| tx.send(e).unwrap()).forget();
    assert!(rx.recv().is_err());
}

#[test]
fn oneshot5() {
    let (c, p) = oneshot::<i32>();
    let t = thread::spawn(|| drop(c));
    let (tx, rx) = channel();
    p.map(move |t| tx.send(t).unwrap()).forget();
    t.join().unwrap();
    assert!(rx.recv().is_err());
}

#[test]
fn oneshot6() {
    let (c, p) = oneshot::<i32>();
    drop(p);
    c.complete(2);
}

#[test]
fn cancel1() {
    let (c, p) = oneshot::<i32>();
    drop(c);
    p.map(|_| panic!()).forget();
}

#[test]
fn map_err1() {
    finished::<i32, i32>(1).map_err(|_| panic!()).forget();
}

#[test]
fn map_err2() {
    let (tx, rx) = channel();
    failed::<i32, i32>(1).map_err(move |v| tx.send(v).unwrap()).forget();
    assert_eq!(rx.recv(), Ok(1));
    assert!(rx.recv().is_err());
}

#[test]
fn map_err3() {
    let (c, p) = oneshot::<i32>();
    p.map_err(|_| {}).forget();
    drop(c);
}

#[test]
fn or_else1() {
    let (c1, p1) = oneshot::<i32>();
    let (c2, p2) = oneshot::<i32>();

    let (tx, rx) = channel();
    let tx2 = tx.clone();
    let p1 = p1.map_err(move |i| { tx2.send(2).unwrap(); i });
    let tx2 = tx.clone();
    let p2 = p2.map(move |i| { tx2.send(i).unwrap(); i });

    assert!(rx.try_recv().is_err());
    drop(c1);
    c2.complete(3);
    p1.or_else(|_| p2).map(move |v| tx.send(v).unwrap()).forget();

    assert_eq!(rx.recv(), Ok(2));
    assert_eq!(rx.recv(), Ok(3));
    assert_eq!(rx.recv(), Ok(3));
    assert!(rx.recv().is_err());
}

#[test]
fn or_else2() {
    let (c1, p1) = oneshot::<i32>();

    let (tx, rx) = channel();

    p1.or_else(move |_| {
        tx.send(()).unwrap();
        finished::<i32, i32>(1)
    }).forget();

    c1.complete(2);
    assert!(rx.recv().is_err());
}

#[test]
fn join1() {
    let (tx, rx) = channel();
    finished::<i32, i32>(1).join(finished(2))
                           .map(move |v| tx.send(v).unwrap())
                           .forget();
    assert_eq!(rx.recv(), Ok((1, 2)));
    assert!(rx.recv().is_err());
}

#[test]
fn join2() {
    let (c1, p1) = oneshot::<i32>();
    let (c2, p2) = oneshot::<i32>();
    let (tx, rx) = channel();
    p1.join(p2).map(move |v| tx.send(v).unwrap()).forget();
    assert!(rx.try_recv().is_err());
    c1.complete(1);
    assert!(rx.try_recv().is_err());
    c2.complete(2);
    assert_eq!(rx.recv(), Ok((1, 2)));
    assert!(rx.recv().is_err());
}

#[test]
fn join3() {
    let (c1, p1) = oneshot::<i32>();
    let (c2, p2) = oneshot::<i32>();
    let (tx, rx) = channel();
    p1.join(p2).map_err(move |_v| tx.send(1).unwrap()).forget();
    assert!(rx.try_recv().is_err());
    drop(c1);
    assert_eq!(rx.recv(), Ok(1));
    assert!(rx.recv().is_err());
    drop(c2);
}

#[test]
fn join4() {
    let (c1, p1) = oneshot::<i32>();
    let (c2, p2) = oneshot::<i32>();
    let (tx, rx) = channel();
    p1.join(p2).map_err(move |v| tx.send(v).unwrap()).forget();
    assert!(rx.try_recv().is_err());
    drop(c1);
    assert!(rx.recv().is_ok());
    drop(c2);
    assert!(rx.recv().is_err());
}

#[test]
fn join5() {
    let (c1, p1) = oneshot::<i32>();
    let (c2, p2) = oneshot::<i32>();
    let (c3, p3) = oneshot::<i32>();
    let (tx, rx) = channel();
    p1.join(p2).join(p3).map(move |v| tx.send(v).unwrap()).forget();
    assert!(rx.try_recv().is_err());
    c1.complete(1);
    assert!(rx.try_recv().is_err());
    c2.complete(2);
    assert!(rx.try_recv().is_err());
    c3.complete(3);
    assert_eq!(rx.recv(), Ok(((1, 2), 3)));
    assert!(rx.recv().is_err());
}

#[test]
fn select1() {
    let (c1, p1) = oneshot::<i32>();
    let (c2, p2) = oneshot::<i32>();
    let (tx, rx) = channel();
    p1.select(p2).map(move |v| tx.send(v).unwrap()).forget();
    assert!(rx.try_recv().is_err());
    c1.complete(1);
    let (v, p2) = rx.recv().unwrap();
    assert_eq!(v, 1);
    assert!(rx.recv().is_err());

    let (tx, rx) = channel();
    p2.map(move |v| tx.send(v).unwrap()).forget();
    c2.complete(2);
    assert_eq!(rx.recv(), Ok(2));
    assert!(rx.recv().is_err());
}

#[test]
fn select2() {
    let (c1, p1) = oneshot::<i32>();
    let (c2, p2) = oneshot::<i32>();
    let (tx, rx) = channel();
    p1.select(p2).map_err(move |v| tx.send((1, v.1)).unwrap()).forget();
    assert!(rx.try_recv().is_err());
    drop(c1);
    let (v, p2) = rx.recv().unwrap();
    assert_eq!(v, 1);
    assert!(rx.recv().is_err());

    let (tx, rx) = channel();
    p2.map(move |v| tx.send(v).unwrap()).forget();
    c2.complete(2);
    assert_eq!(rx.recv(), Ok(2));
    assert!(rx.recv().is_err());
}

#[test]
fn select3() {
    let (c1, p1) = oneshot::<i32>();
    let (c2, p2) = oneshot::<i32>();
    let (tx, rx) = channel();
    p1.select(p2).map_err(move |v| tx.send((1, v.1)).unwrap()).forget();
    assert!(rx.try_recv().is_err());
    drop(c1);
    let (v, p2) = rx.recv().unwrap();
    assert_eq!(v, 1);
    assert!(rx.recv().is_err());

    let (tx, rx) = channel();
    p2.map_err(move |_v| tx.send(2).unwrap()).forget();
    drop(c2);
    assert_eq!(rx.recv(), Ok(2));
    assert!(rx.recv().is_err());
}

#[test]
fn select4() {
    let (tx, rx) = channel::<Complete<i32>>();

    let t = thread::spawn(move || {
        for c in rx {
            c.complete(1);
        }
    });

    let (tx2, rx2) = channel();
    for _ in 0..10000 {
        let (c1, p1) = oneshot::<i32>();
        let (c2, p2) = oneshot::<i32>();

        let tx3 = tx2.clone();
        p1.select(p2).map(move |_| tx3.send(()).unwrap()).forget();
        tx.send(c1).unwrap();
        rx2.recv().unwrap();
        drop(c2);
    }
    drop(tx);

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


<commit_before>use flate2::read::GzDecoder;
use std::fs::{read_to_string, write};
use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;

static REVISION: &'static str = "7979016aff545f7b41cc517031026020b340989d";

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }
    let path_string = path.to_string_lossy();
    let path_string = if cfg!(windows) {
        path_string.replace('\\', "/").into()
    } else {
        path_string
    };
    // TODO assert that parsing fails on the parse-fail cases
    if path_string.starts_with("tests/rust/src/test/parse-fail")
        || path_string.starts_with("tests/rust/src/test/compile-fail")
        || path_string.starts_with("tests/rust/src/test/rustfix")
    {
        return false;
    }

    if path_string.starts_with("tests/rust/src/test/ui") {
        let stderr_path = path.with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    match path_string.as_ref() {
        // Deprecated placement syntax
        "tests/rust/src/test/ui/obsolete-in-place/bad.rs" |
        // Deprecated anonymous parameter syntax in traits
        "tests/rust/src/test/ui/error-codes/e0119/auxiliary/issue-23563-a.rs" |
        "tests/rust/src/test/ui/issues/issue-13105.rs" |
        "tests/rust/src/test/ui/issues/issue-13775.rs" |
        "tests/rust/src/test/ui/issues/issue-34074.rs" |
        // Deprecated await macro syntax
        "tests/rust/src/test/ui/async-await/await-macro.rs" |
        // 2015-style dyn that libsyntax rejects
        "tests/rust/src/test/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs" |
        // not actually test cases
        "tests/rust/src/test/ui/include-single-expr-helper.rs" |
        "tests/rust/src/test/ui/include-single-expr-helper-1.rs" |
        "tests/rust/src/test/ui/issues/auxiliary/issue-21146-inc.rs" |
        "tests/rust/src/test/ui/macros/auxiliary/macro-comma-support.rs" |
        "tests/rust/src/test/ui/macros/auxiliary/macro-include-items-expr.rs" => false,
        _ => true,
    }
}

pub fn clone_rust() {
    let needs_clone = match read_to_string("tests/rust/COMMIT") {
        Err(_) => true,
        Ok(contents) => contents.trim() != REVISION,
    };
    if needs_clone {
        download_and_unpack().unwrap();
    }
}

fn download_and_unpack() -> Result<(), Box<dyn std::error::Error>> {
    let url = format!(
        "https://github.com/rust-lang/rust/archive/{}.tar.gz",
        REVISION
    );
    let request = reqwest::get(&url)?;
    let decoder = GzDecoder::new(request);
    let mut archive = Archive::new(decoder);
    let prefix = format!("rust-{}", REVISION);
    for mut entry in archive.entries()?.filter_map(|e| e.ok()) {
        if entry.path()?.starts_with(&prefix[..]) {
            let path =
                Path::new("tests/rust").join(entry.path()?.strip_prefix(&prefix[..])?.to_owned());
            entry.unpack(&path)?;
        }
    }
    write("tests/rust/COMMIT", REVISION)?;
    Ok(())
}
<commit_msg>Remove std::fs function imports<commit_after>use flate2::read::GzDecoder;
use std::fs;
use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;

static REVISION: &'static str = "7979016aff545f7b41cc517031026020b340989d";

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }
    let path_string = path.to_string_lossy();
    let path_string = if cfg!(windows) {
        path_string.replace('\\', "/").into()
    } else {
        path_string
    };
    // TODO assert that parsing fails on the parse-fail cases
    if path_string.starts_with("tests/rust/src/test/parse-fail")
        || path_string.starts_with("tests/rust/src/test/compile-fail")
        || path_string.starts_with("tests/rust/src/test/rustfix")
    {
        return false;
    }

    if path_string.starts_with("tests/rust/src/test/ui") {
        let stderr_path = path.with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    match path_string.as_ref() {
        // Deprecated placement syntax
        "tests/rust/src/test/ui/obsolete-in-place/bad.rs" |
        // Deprecated anonymous parameter syntax in traits
        "tests/rust/src/test/ui/error-codes/e0119/auxiliary/issue-23563-a.rs" |
        "tests/rust/src/test/ui/issues/issue-13105.rs" |
        "tests/rust/src/test/ui/issues/issue-13775.rs" |
        "tests/rust/src/test/ui/issues/issue-34074.rs" |
        // Deprecated await macro syntax
        "tests/rust/src/test/ui/async-await/await-macro.rs" |
        // 2015-style dyn that libsyntax rejects
        "tests/rust/src/test/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs" |
        // not actually test cases
        "tests/rust/src/test/ui/include-single-expr-helper.rs" |
        "tests/rust/src/test/ui/include-single-expr-helper-1.rs" |
        "tests/rust/src/test/ui/issues/auxiliary/issue-21146-inc.rs" |
        "tests/rust/src/test/ui/macros/auxiliary/macro-comma-support.rs" |
        "tests/rust/src/test/ui/macros/auxiliary/macro-include-items-expr.rs" => false,
        _ => true,
    }
}

pub fn clone_rust() {
    let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
        Err(_) => true,
        Ok(contents) => contents.trim() != REVISION,
    };
    if needs_clone {
        download_and_unpack().unwrap();
    }
}

fn download_and_unpack() -> Result<(), Box<dyn std::error::Error>> {
    let url = format!(
        "https://github.com/rust-lang/rust/archive/{}.tar.gz",
        REVISION
    );
    let request = reqwest::get(&url)?;
    let decoder = GzDecoder::new(request);
    let mut archive = Archive::new(decoder);
    let prefix = format!("rust-{}", REVISION);
    for mut entry in archive.entries()?.filter_map(|e| e.ok()) {
        if entry.path()?.starts_with(&prefix[..]) {
            let path =
                Path::new("tests/rust").join(entry.path()?.strip_prefix(&prefix[..])?.to_owned());
            entry.unpack(&path)?;
        }
    }
    fs::write("tests/rust/COMMIT", REVISION)?;
    Ok(())
}
<|endoftext|>


<commit_before>import std::{vec, str, option};
import option::{some, none};
import syntax::ast::*;
import syntax::visit;
import syntax::ast_util;

tag deref_t { unbox; field; index; }

type deref = @{mut: bool, kind: deref_t, outer_t: ty::t};

// Finds the root (the thing that is dereferenced) for the given expr, and a
// vec of dereferences that were used on this root. Note that, in this vec,
// the inner derefs come in front, so foo.bar[1] becomes rec(ex=foo,
// ds=[index,field])
fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
   {ex: @expr, ds: @[deref]} {
    fn maybe_auto_unbox(tcx: ty::ctxt, t: ty::t) -> {t: ty::t, ds: [deref]} {
        let ds = [];
        while true {
            alt ty::struct(tcx, t) {
              ty::ty_box(mt) {
                ds += [@{mut: mt.mut != imm, kind: unbox, outer_t: t}];
                t = mt.ty;
              }
              ty::ty_uniq(mt) {
                ds += [@{mut: mt.mut != imm, kind: unbox, outer_t: t}];
                t = mt.ty;
              }
              ty::ty_res(_, inner, tps) {
                ds += [@{mut: false, kind: unbox, outer_t: t}];
                t = ty::substitute_type_params(tcx, tps, inner);
              }
              ty::ty_tag(did, tps) {
                let variants = ty::tag_variants(tcx, did);
                if vec::len(variants) != 1u ||
                       vec::len(variants[0].args) != 1u {
                    break;
                }
                ds += [@{mut: false, kind: unbox, outer_t: t}];
                t = ty::substitute_type_params(tcx, tps, variants[0].args[0]);
              }
              _ { break; }
            }
        }
        ret {t: t, ds: ds};
    }
    let ds: [deref] = [];
    while true {
        alt copy ex.node {
          expr_field(base, ident) {
            let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, base));
            let is_mut = false;
            alt ty::struct(tcx, auto_unbox.t) {
              ty::ty_rec(fields) {
                for fld: ty::field in fields {
                    if str::eq(ident, fld.ident) {
                        is_mut = fld.mt.mut == mut;
                        break;
                    }
                }
              }
              ty::ty_obj(_) { }
            }
            ds += [@{mut: is_mut, kind: field, outer_t: auto_unbox.t}];
            ds += auto_unbox.ds;
            ex = base;
          }
          expr_index(base, _) {
            let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, base));
            alt ty::struct(tcx, auto_unbox.t) {
              ty::ty_vec(mt) {
                ds +=
                    [@{mut: mt.mut == mut,
                       kind: index,
                       outer_t: auto_unbox.t}];
              }
              ty::ty_str. {
                ds += [@{mut: false, kind: index, outer_t: auto_unbox.t}];
              }
            }
            ds += auto_unbox.ds;
            ex = base;
          }
          expr_unary(op, base) {
            if op == deref {
                let base_t = ty::expr_ty(tcx, base);
                let is_mut = false;
                alt ty::struct(tcx, base_t) {
                  ty::ty_box(mt) { is_mut = mt.mut == mut; }
                  ty::ty_uniq(mt) { is_mut = mt.mut == mut; }
                  ty::ty_res(_, _, _) { }
                  ty::ty_tag(_, _) { }
                  ty::ty_ptr(mt) { is_mut = mt.mut == mut; }
                }
                ds += [@{mut: is_mut, kind: unbox, outer_t: base_t}];
                ex = base;
            } else { break; }
          }
          _ { break; }
        }
    }
    if autoderef {
        let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, ex));
        ds += auto_unbox.ds;
    }
    ret {ex: ex, ds: @ds};
}

// Actual mut-checking pass

type mut_map = std::map::hashmap<node_id, ()>;
type ctx = {tcx: ty::ctxt, mut_map: mut_map};

fn check_crate(tcx: ty::ctxt, crate: @crate) -> mut_map {
    let cx = @{tcx: tcx, mut_map: std::map::new_int_hash()};
    let v =
        @{visit_expr: bind visit_expr(cx, _, _, _),
          visit_decl: bind visit_decl(cx, _, _, _)
             with *visit::default_visitor::<()>()};
    visit::visit_crate(*crate, (), visit::mk_vt(v));
    ret cx.mut_map;
}

tag msg { msg_assign; msg_move_out; msg_mut_ref; }

fn mk_err(cx: @ctx, span: syntax::codemap::span, msg: msg, name: str) {
    cx.tcx.sess.span_err(span, alt msg {
      msg_assign. { "assigning to " + name }
      msg_move_out. { "moving out of " + name }
      msg_mut_ref. { "passing " + name + " by mutable reference" }
    });
}

fn visit_decl(cx: @ctx, d: @decl, &&e: (), v: visit::vt<()>) {
    visit::visit_decl(d, e, v);
    alt d.node {
      decl_local(locs) {
        for (_, loc) in locs {
            alt loc.node.init {
              some(init) {
                if init.op == init_move { check_move_rhs(cx, init.expr); }
              }
              none. { }
            }
        }
      }
      _ { }
    }
}

fn visit_expr(cx: @ctx, ex: @expr, &&e: (), v: visit::vt<()>) {
    alt ex.node {
      expr_call(f, args) { check_call(cx, f, args); }
      expr_swap(lhs, rhs) {
        check_lval(cx, lhs, msg_assign);
        check_lval(cx, rhs, msg_assign);
      }
      expr_move(dest, src) {
        check_lval(cx, dest, msg_assign);
        check_move_rhs(cx, src);
      }
      expr_assign(dest, src) | expr_assign_op(_, dest, src) {
        check_lval(cx, dest, msg_assign);
      }
      _ { }
    }
    visit::visit_expr(ex, e, v);
}

fn check_lval(cx: @ctx, dest: @expr, msg: msg) {
    alt dest.node {
      expr_path(p) {
        let def = cx.tcx.def_map.get(dest.id);
        alt is_immutable_def(def) {
          some(name) { mk_err(cx, dest.span, msg, name); }
          _ { }
        }
        cx.mut_map.insert(ast_util::def_id_of_def(def).node, ());
      }
      _ {
        let root = expr_root(cx.tcx, dest, false);
        if vec::len(*root.ds) == 0u {
            if msg != msg_move_out {
                mk_err(cx, dest.span, msg, "non-lvalue");
            }
        } else if !root.ds[0].mut {
            let name =
                alt root.ds[0].kind {
                  mut::unbox. { "immutable box" }
                  mut::field. { "immutable field" }
                  mut::index. { "immutable vec content" }
                };
            mk_err(cx, dest.span, msg, name);
        }
      }
    }
}

fn check_move_rhs(cx: @ctx, src: @expr) {
    alt src.node {
      expr_path(p) {
        alt cx.tcx.def_map.get(src.id) {
          def_obj_field(_, _) {
            mk_err(cx, src.span, msg_move_out, "object field");
          }
          _ { }
        }
        check_lval(cx, src, msg_move_out);
      }
      _ {
        let root = expr_root(cx.tcx, src, false);

        // Not a path and no-derefs means this is a temporary.
        if vec::len(*root.ds) != 0u {
            cx.tcx.sess.span_err(src.span, "moving out of a data structure");
        }
      }
    }
}

fn check_call(cx: @ctx, f: @expr, args: [@expr]) {
    let arg_ts = ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f));
    let i = 0u;
    for arg_t: ty::arg in arg_ts {
        alt arg_t.mode {
          by_mut_ref. { check_lval(cx, args[i], msg_mut_ref); }
          by_move. { check_lval(cx, args[i], msg_move_out); }
          _ {}
        }
        i += 1u;
    }
}

fn is_immutable_def(def: def) -> option::t<str> {
    alt def {
      def_fn(_, _) | def_mod(_) | def_native_mod(_) | def_const(_) |
      def_use(_) {
        some("static item")
      }
      def_obj_field(_, imm.) { some("immutable object field") }
      def_upvar(_, inner, mut) {
        if !mut { some("upvar") } else { is_immutable_def(*inner) }
      }
      def_binding(_) { some("binding") }
      def_local(_, let_ref.) { some("by-reference binding") }
      _ { none }
    }
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Correct two more analyses of mutable? as mutable<commit_after>import std::{vec, str, option};
import option::{some, none};
import syntax::ast::*;
import syntax::visit;
import syntax::ast_util;

tag deref_t { unbox; field; index; }

type deref = @{mut: bool, kind: deref_t, outer_t: ty::t};

// Finds the root (the thing that is dereferenced) for the given expr, and a
// vec of dereferences that were used on this root. Note that, in this vec,
// the inner derefs come in front, so foo.bar[1] becomes rec(ex=foo,
// ds=[index,field])
fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
   {ex: @expr, ds: @[deref]} {
    fn maybe_auto_unbox(tcx: ty::ctxt, t: ty::t) -> {t: ty::t, ds: [deref]} {
        let ds = [];
        while true {
            alt ty::struct(tcx, t) {
              ty::ty_box(mt) {
                ds += [@{mut: mt.mut == mut, kind: unbox, outer_t: t}];
                t = mt.ty;
              }
              ty::ty_uniq(mt) {
                ds += [@{mut: mt.mut == mut, kind: unbox, outer_t: t}];
                t = mt.ty;
              }
              ty::ty_res(_, inner, tps) {
                ds += [@{mut: false, kind: unbox, outer_t: t}];
                t = ty::substitute_type_params(tcx, tps, inner);
              }
              ty::ty_tag(did, tps) {
                let variants = ty::tag_variants(tcx, did);
                if vec::len(variants) != 1u ||
                       vec::len(variants[0].args) != 1u {
                    break;
                }
                ds += [@{mut: false, kind: unbox, outer_t: t}];
                t = ty::substitute_type_params(tcx, tps, variants[0].args[0]);
              }
              _ { break; }
            }
        }
        ret {t: t, ds: ds};
    }
    let ds: [deref] = [];
    while true {
        alt copy ex.node {
          expr_field(base, ident) {
            let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, base));
            let is_mut = false;
            alt ty::struct(tcx, auto_unbox.t) {
              ty::ty_rec(fields) {
                for fld: ty::field in fields {
                    if str::eq(ident, fld.ident) {
                        is_mut = fld.mt.mut == mut;
                        break;
                    }
                }
              }
              ty::ty_obj(_) { }
            }
            ds += [@{mut: is_mut, kind: field, outer_t: auto_unbox.t}];
            ds += auto_unbox.ds;
            ex = base;
          }
          expr_index(base, _) {
            let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, base));
            alt ty::struct(tcx, auto_unbox.t) {
              ty::ty_vec(mt) {
                ds +=
                    [@{mut: mt.mut == mut,
                       kind: index,
                       outer_t: auto_unbox.t}];
              }
              ty::ty_str. {
                ds += [@{mut: false, kind: index, outer_t: auto_unbox.t}];
              }
            }
            ds += auto_unbox.ds;
            ex = base;
          }
          expr_unary(op, base) {
            if op == deref {
                let base_t = ty::expr_ty(tcx, base);
                let is_mut = false;
                alt ty::struct(tcx, base_t) {
                  ty::ty_box(mt) { is_mut = mt.mut == mut; }
                  ty::ty_uniq(mt) { is_mut = mt.mut == mut; }
                  ty::ty_res(_, _, _) { }
                  ty::ty_tag(_, _) { }
                  ty::ty_ptr(mt) { is_mut = mt.mut == mut; }
                }
                ds += [@{mut: is_mut, kind: unbox, outer_t: base_t}];
                ex = base;
            } else { break; }
          }
          _ { break; }
        }
    }
    if autoderef {
        let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, ex));
        ds += auto_unbox.ds;
    }
    ret {ex: ex, ds: @ds};
}

// Actual mut-checking pass

type mut_map = std::map::hashmap<node_id, ()>;
type ctx = {tcx: ty::ctxt, mut_map: mut_map};

fn check_crate(tcx: ty::ctxt, crate: @crate) -> mut_map {
    let cx = @{tcx: tcx, mut_map: std::map::new_int_hash()};
    let v =
        @{visit_expr: bind visit_expr(cx, _, _, _),
          visit_decl: bind visit_decl(cx, _, _, _)
             with *visit::default_visitor::<()>()};
    visit::visit_crate(*crate, (), visit::mk_vt(v));
    ret cx.mut_map;
}

tag msg { msg_assign; msg_move_out; msg_mut_ref; }

fn mk_err(cx: @ctx, span: syntax::codemap::span, msg: msg, name: str) {
    cx.tcx.sess.span_err(span, alt msg {
      msg_assign. { "assigning to " + name }
      msg_move_out. { "moving out of " + name }
      msg_mut_ref. { "passing " + name + " by mutable reference" }
    });
}

fn visit_decl(cx: @ctx, d: @decl, &&e: (), v: visit::vt<()>) {
    visit::visit_decl(d, e, v);
    alt d.node {
      decl_local(locs) {
        for (_, loc) in locs {
            alt loc.node.init {
              some(init) {
                if init.op == init_move { check_move_rhs(cx, init.expr); }
              }
              none. { }
            }
        }
      }
      _ { }
    }
}

fn visit_expr(cx: @ctx, ex: @expr, &&e: (), v: visit::vt<()>) {
    alt ex.node {
      expr_call(f, args) { check_call(cx, f, args); }
      expr_swap(lhs, rhs) {
        check_lval(cx, lhs, msg_assign);
        check_lval(cx, rhs, msg_assign);
      }
      expr_move(dest, src) {
        check_lval(cx, dest, msg_assign);
        check_move_rhs(cx, src);
      }
      expr_assign(dest, src) | expr_assign_op(_, dest, src) {
        check_lval(cx, dest, msg_assign);
      }
      _ { }
    }
    visit::visit_expr(ex, e, v);
}

fn check_lval(cx: @ctx, dest: @expr, msg: msg) {
    alt dest.node {
      expr_path(p) {
        let def = cx.tcx.def_map.get(dest.id);
        alt is_immutable_def(def) {
          some(name) { mk_err(cx, dest.span, msg, name); }
          _ { }
        }
        cx.mut_map.insert(ast_util::def_id_of_def(def).node, ());
      }
      _ {
        let root = expr_root(cx.tcx, dest, false);
        if vec::len(*root.ds) == 0u {
            if msg != msg_move_out {
                mk_err(cx, dest.span, msg, "non-lvalue");
            }
        } else if !root.ds[0].mut {
            let name =
                alt root.ds[0].kind {
                  mut::unbox. { "immutable box" }
                  mut::field. { "immutable field" }
                  mut::index. { "immutable vec content" }
                };
            mk_err(cx, dest.span, msg, name);
        }
      }
    }
}

fn check_move_rhs(cx: @ctx, src: @expr) {
    alt src.node {
      expr_path(p) {
        alt cx.tcx.def_map.get(src.id) {
          def_obj_field(_, _) {
            mk_err(cx, src.span, msg_move_out, "object field");
          }
          _ { }
        }
        check_lval(cx, src, msg_move_out);
      }
      _ {
        let root = expr_root(cx.tcx, src, false);

        // Not a path and no-derefs means this is a temporary.
        if vec::len(*root.ds) != 0u {
            cx.tcx.sess.span_err(src.span, "moving out of a data structure");
        }
      }
    }
}

fn check_call(cx: @ctx, f: @expr, args: [@expr]) {
    let arg_ts = ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f));
    let i = 0u;
    for arg_t: ty::arg in arg_ts {
        alt arg_t.mode {
          by_mut_ref. { check_lval(cx, args[i], msg_mut_ref); }
          by_move. { check_lval(cx, args[i], msg_move_out); }
          _ {}
        }
        i += 1u;
    }
}

fn is_immutable_def(def: def) -> option::t<str> {
    alt def {
      def_fn(_, _) | def_mod(_) | def_native_mod(_) | def_const(_) |
      def_use(_) {
        some("static item")
      }
      def_obj_field(_, imm.) { some("immutable object field") }
      def_upvar(_, inner, mut) {
        if !mut { some("upvar") } else { is_immutable_def(*inner) }
      }
      def_binding(_) { some("binding") }
      def_local(_, let_ref.) { some("by-reference binding") }
      _ { none }
    }
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


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

use std::borrow::Borrow;
use std::cmp;
use std::fmt;
use std::hash;
use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use std::rc::Rc;
use std::slice;
use std::str;
use std::usize;

/// A string that is either shared (heap-allocated and reference-counted) or borrowed.
///
/// Equivalent to `enum { Borrowed(&'a str), Shared(Rc<String>) }`, but stored more compactly.
///
/// FIXME(https://github.com/rust-lang/rfcs/issues/1230): use an actual enum if/when
/// the compiler can do this layout optimization.
pub struct CowRcStr<'a> {
    /// FIXME: https://github.com/rust-lang/rust/issues/27730 use NonZero or Shared.
    /// In the meantime we abuse `&'static _` to get the effect of `NonZero<*const _>`.
    /// `ptr` doesn’t really have the 'static lifetime!
    ptr: &'static (),

    /// * If `borrowed_len_or_max == usize::MAX`, then `ptr` represents `NonZero<*const String>`
    ///   from `Rc::into_raw`.
    ///   The lifetime parameter `'a` is irrelevant in this case.
    ///
    /// * Otherwise, `ptr` represents the `NonZero<*const u8>` data component of `&'a str`,
    ///   and `borrowed_len_or_max` its length.
    borrowed_len_or_max: usize,

    phantom: PhantomData<Result<&'a str, Rc<String>>>,
}

fn _static_assert_same_size<'a>() {
    // "Instantiate" the generic function without calling it.
    let _ = mem::transmute::<CowRcStr<'a>, Option<CowRcStr<'a>>>;
}

impl<'a> From<&'a str> for CowRcStr<'a> {
    #[inline]
    fn from(s: &'a str) -> Self {
        let len = s.len();
        assert!(len < usize::MAX);
        CowRcStr {
            ptr: unsafe { &*(s.as_ptr() as *const ()) },
            borrowed_len_or_max: len,
            phantom: PhantomData,
        }
    }
}

impl<'a> From<String> for CowRcStr<'a> {
    #[inline]
    fn from(s: String) -> Self {
        CowRcStr::from_rc(Rc::new(s))
    }
}

impl<'a> CowRcStr<'a> {
    #[inline]
    fn from_rc(s: Rc<String>) -> Self {
        let ptr = unsafe { &*(Rc::into_raw(s) as *const ()) };
        CowRcStr {
            ptr: ptr,
            borrowed_len_or_max: usize::MAX,
            phantom: PhantomData,
        }
    }

    #[inline]
    fn unpack(&self) -> Result<&'a str, *const String> {
        if self.borrowed_len_or_max == usize::MAX {
            Err(self.ptr as *const () as *const String)
        } else {
            unsafe {
                Ok(str::from_utf8_unchecked(slice::from_raw_parts(
                    self.ptr as *const () as *const u8,
                    self.borrowed_len_or_max,
                )))
            }
        }
    }

    /// Convert into `String`, re-using an existing memory allocation if possible.
    #[inline]
    pub fn into_owned(self) -> String {
        let unpacked = self.unpack();

        // Inhibit destructor: we’re taking ownership of this strong reference (if any)
        mem::forget(self);

        match unpacked {
            Ok(s) => s.to_owned(),
            Err(ptr) => {
                let rc = unsafe {
                    Rc::from_raw(ptr)
                };
                Rc::try_unwrap(rc).unwrap_or_else(|rc| (*rc).clone())
            }
        }
    }
}

impl<'a> Clone for CowRcStr<'a> {
    #[inline]
    fn clone(&self) -> Self {
        match self.unpack() {
            Err(ptr) => {
                let rc = unsafe {
                    Rc::from_raw(ptr)
                };
                let new_rc = rc.clone();
                mem::forget(rc);  // Don’t actually take ownership of this strong reference
                CowRcStr::from_rc(new_rc)
            }
            Ok(_) => {
                CowRcStr { ..*self }
            }
        }
    }
}

impl<'a> Drop for CowRcStr<'a> {
    #[inline]
    fn drop(&mut self) {
        if let Err(ptr) = self.unpack() {
            mem::drop(unsafe {
                Rc::from_raw(ptr)
            })
        }
    }
}

impl<'a> Deref for CowRcStr<'a> {
    type Target = str;

    #[inline]
    fn deref(&self) -> &str {
        self.unpack().unwrap_or_else(|ptr| unsafe {
            &**ptr
        })
    }
}

// Boilerplate / trivial impls below.

impl<'a> AsRef<str> for CowRcStr<'a> {
    #[inline]
    fn as_ref(&self) -> &str {
        self
    }
}

impl<'a> Borrow<str> for CowRcStr<'a> {
    #[inline]
    fn borrow(&self) -> &str {
        self
    }
}

impl<'a> Default for CowRcStr<'a> {
    #[inline]
    fn default() -> Self {
        Self::from("")
    }
}

impl<'a> hash::Hash for CowRcStr<'a> {
    #[inline]
    fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
        str::hash(self, hasher)
    }
}

impl<'a, T: AsRef<str>> PartialEq<T> for CowRcStr<'a> {
    #[inline]
    fn eq(&self, other: &T) -> bool {
        str::eq(self, other.as_ref())
    }
}

impl<'a, T: AsRef<str>> PartialOrd<T> for CowRcStr<'a> {
    #[inline]
    fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
        str::partial_cmp(self, other.as_ref())
    }
}

impl<'a> Eq for CowRcStr<'a> {}

impl<'a> Ord for CowRcStr<'a> {
    #[inline]
    fn cmp(&self, other: &Self) -> cmp::Ordering {
        str::cmp(self, other)
    }
}

impl<'a> fmt::Display for CowRcStr<'a> {
    #[inline]
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        str::fmt(self, formatter)
    }
}

impl<'a> fmt::Debug for CowRcStr<'a> {
    #[inline]
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        str::fmt(self, formatter)
    }
}
<commit_msg>Add `From<Cow<str>> for CowRcStr`<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::borrow::{Borrow, Cow};
use std::cmp;
use std::fmt;
use std::hash;
use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use std::rc::Rc;
use std::slice;
use std::str;
use std::usize;

/// A string that is either shared (heap-allocated and reference-counted) or borrowed.
///
/// Equivalent to `enum { Borrowed(&'a str), Shared(Rc<String>) }`, but stored more compactly.
///
/// FIXME(https://github.com/rust-lang/rfcs/issues/1230): use an actual enum if/when
/// the compiler can do this layout optimization.
pub struct CowRcStr<'a> {
    /// FIXME: https://github.com/rust-lang/rust/issues/27730 use NonZero or Shared.
    /// In the meantime we abuse `&'static _` to get the effect of `NonZero<*const _>`.
    /// `ptr` doesn’t really have the 'static lifetime!
    ptr: &'static (),

    /// * If `borrowed_len_or_max == usize::MAX`, then `ptr` represents `NonZero<*const String>`
    ///   from `Rc::into_raw`.
    ///   The lifetime parameter `'a` is irrelevant in this case.
    ///
    /// * Otherwise, `ptr` represents the `NonZero<*const u8>` data component of `&'a str`,
    ///   and `borrowed_len_or_max` its length.
    borrowed_len_or_max: usize,

    phantom: PhantomData<Result<&'a str, Rc<String>>>,
}

fn _static_assert_same_size<'a>() {
    // "Instantiate" the generic function without calling it.
    let _ = mem::transmute::<CowRcStr<'a>, Option<CowRcStr<'a>>>;
}

impl<'a> From<Cow<'a, str>> for CowRcStr<'a> {
    #[inline]
    fn from(s: Cow<'a, str>) -> Self {
        match s {
            Cow::Borrowed(s) => CowRcStr::from(s),
            Cow::Owned(s) => CowRcStr::from(s),
        }
    }
}

impl<'a> From<&'a str> for CowRcStr<'a> {
    #[inline]
    fn from(s: &'a str) -> Self {
        let len = s.len();
        assert!(len < usize::MAX);
        CowRcStr {
            ptr: unsafe { &*(s.as_ptr() as *const ()) },
            borrowed_len_or_max: len,
            phantom: PhantomData,
        }
    }
}

impl<'a> From<String> for CowRcStr<'a> {
    #[inline]
    fn from(s: String) -> Self {
        CowRcStr::from_rc(Rc::new(s))
    }
}

impl<'a> CowRcStr<'a> {
    #[inline]
    fn from_rc(s: Rc<String>) -> Self {
        let ptr = unsafe { &*(Rc::into_raw(s) as *const ()) };
        CowRcStr {
            ptr: ptr,
            borrowed_len_or_max: usize::MAX,
            phantom: PhantomData,
        }
    }

    #[inline]
    fn unpack(&self) -> Result<&'a str, *const String> {
        if self.borrowed_len_or_max == usize::MAX {
            Err(self.ptr as *const () as *const String)
        } else {
            unsafe {
                Ok(str::from_utf8_unchecked(slice::from_raw_parts(
                    self.ptr as *const () as *const u8,
                    self.borrowed_len_or_max,
                )))
            }
        }
    }

    /// Convert into `String`, re-using an existing memory allocation if possible.
    #[inline]
    pub fn into_owned(self) -> String {
        let unpacked = self.unpack();

        // Inhibit destructor: we’re taking ownership of this strong reference (if any)
        mem::forget(self);

        match unpacked {
            Ok(s) => s.to_owned(),
            Err(ptr) => {
                let rc = unsafe {
                    Rc::from_raw(ptr)
                };
                Rc::try_unwrap(rc).unwrap_or_else(|rc| (*rc).clone())
            }
        }
    }
}

impl<'a> Clone for CowRcStr<'a> {
    #[inline]
    fn clone(&self) -> Self {
        match self.unpack() {
            Err(ptr) => {
                let rc = unsafe {
                    Rc::from_raw(ptr)
                };
                let new_rc = rc.clone();
                mem::forget(rc);  // Don’t actually take ownership of this strong reference
                CowRcStr::from_rc(new_rc)
            }
            Ok(_) => {
                CowRcStr { ..*self }
            }
        }
    }
}

impl<'a> Drop for CowRcStr<'a> {
    #[inline]
    fn drop(&mut self) {
        if let Err(ptr) = self.unpack() {
            mem::drop(unsafe {
                Rc::from_raw(ptr)
            })
        }
    }
}

impl<'a> Deref for CowRcStr<'a> {
    type Target = str;

    #[inline]
    fn deref(&self) -> &str {
        self.unpack().unwrap_or_else(|ptr| unsafe {
            &**ptr
        })
    }
}

// Boilerplate / trivial impls below.

impl<'a> AsRef<str> for CowRcStr<'a> {
    #[inline]
    fn as_ref(&self) -> &str {
        self
    }
}

impl<'a> Borrow<str> for CowRcStr<'a> {
    #[inline]
    fn borrow(&self) -> &str {
        self
    }
}

impl<'a> Default for CowRcStr<'a> {
    #[inline]
    fn default() -> Self {
        Self::from("")
    }
}

impl<'a> hash::Hash for CowRcStr<'a> {
    #[inline]
    fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
        str::hash(self, hasher)
    }
}

impl<'a, T: AsRef<str>> PartialEq<T> for CowRcStr<'a> {
    #[inline]
    fn eq(&self, other: &T) -> bool {
        str::eq(self, other.as_ref())
    }
}

impl<'a, T: AsRef<str>> PartialOrd<T> for CowRcStr<'a> {
    #[inline]
    fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
        str::partial_cmp(self, other.as_ref())
    }
}

impl<'a> Eq for CowRcStr<'a> {}

impl<'a> Ord for CowRcStr<'a> {
    #[inline]
    fn cmp(&self, other: &Self) -> cmp::Ordering {
        str::cmp(self, other)
    }
}

impl<'a> fmt::Display for CowRcStr<'a> {
    #[inline]
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        str::fmt(self, formatter)
    }
}

impl<'a> fmt::Debug for CowRcStr<'a> {
    #[inline]
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        str::fmt(self, formatter)
    }
}
<|endoftext|>


<commit_before>use core::fmt;

use io::Write;

use hal::{app, console};

#[cfg(not(test))]
#[lang = "stack_exhausted"]
pub fn stack_exhausted() -> ! {
    unimplemented!()
}

#[cfg(not(test))]
#[lang = "eh_personality"]
pub fn eh_personality() -> ! {
    unimplemented!()
}

#[cfg(not(test))]
#[lang = "panic_fmt"]
pub extern fn panic_impl(msg: fmt::Arguments, file: &'static str, line: u32) {
    // Use raw console to be sure to not be locked
    console().write_fmt(format_args!("Panic at '{}:{}' with message '{}'\n\r",
                                     file, line, msg)).unwrap();
    console().flush().unwrap();

    app::crash();

    loop {}
}

#[no_mangle]
#[allow(non_snake_case)]
pub fn _Unwind_Resume(_: *mut u8) -> ! {
    panic!("_Unwind_Resume called");
}
<commit_msg>utils/lang: Silence a clippy warning<commit_after>use core::fmt;

use io::Write;

use hal::{app, console};

#[cfg(not(test))]
#[lang = "stack_exhausted"]
pub fn stack_exhausted() -> ! {
    unimplemented!()
}

#[cfg(not(test))]
#[lang = "eh_personality"]
pub fn eh_personality() -> ! {
    unimplemented!()
}

#[cfg(not(test))]
#[cfg_attr(feature = "clippy", allow(empty_loop))]
#[lang = "panic_fmt"]
pub extern fn panic_impl(msg: fmt::Arguments, file: &'static str, line: u32) {
    // Use raw console to be sure to not be locked
    console().write_fmt(format_args!("Panic at '{}:{}' with message '{}'\n\r",
                                     file, line, msg)).unwrap();
    console().flush().unwrap();

    app::crash();

    loop {}
}

#[no_mangle]
#[allow(non_snake_case)]
pub fn _Unwind_Resume(_: *mut u8) -> ! {
    panic!("_Unwind_Resume called");
}
<|endoftext|>


<commit_before>// todo:
// for _into methods, add two more generic types `D` and `T`.
// `D` will be specific to just those functions
// `T` will be generic across the whole Vector<C>
//
// change to: pub trait Vector<C, T> {}
// and it will be impl'd like this:
// impl Vector<f32, Vector2> for Vector2f {}
//
// then add getters/setters to Vector2
// (if needed) make Vector2 not a Sub-Trait of Vector
//
// then the trait bound on `D` can be `where D: T`
// this allows us to just call setters on D no matter what type it is.
// need to evaluate performance of this concept.
//

// todo: change zero to clear or something like that
pub trait Vector<C>
    where Self: Sized
{
    fn add<'a, V>(&mut self, rhs: &'a V) -> &mut Self where Self: From<&'a V>;
    fn add_into<'a, V>(&self, rhs: &'a V, dest: &mut Self) where Self: From<&'a V>;
    fn angle<'a, V>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn angle_cos<'a, V>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn distance<'a, V>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn distance_sq<'a, V>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn dot<'a, V>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn fma<'a, V>(&mut self, a: &'a V, b: &'a V) -> &mut Self where Self: From<&'a V>;
    fn fma_into<'a, V>(&self, a: &'a V, b: &'a V, dest: &mut Self) where Self: From<&'a V>;
    fn length(&self) -> C;
    fn length_sq(&self) -> C;
    fn lerp<'a, V>(&mut self, other: &'a V, t: C) -> &mut Self where Self: From<&'a V>;
    fn lerp_into<'a, V>(&self, other: &'a V, t: C, dest: &mut Self) where Self: From<&'a V>;
    fn mul<'a, V>(&mut self, rhs: &'a V) -> &mut Self where Self: From<&'a V>;
    fn mul_into<'a, V>(&self, rhs: &'a V, dest: &mut Self) where Self: From<&'a V>;
    fn negate(&mut self) -> &mut Self;
    fn negate_into(&self, dest: &mut Self);
    fn normalize(&mut self) -> &mut Self;
    fn normalize_into(&self, dest: &mut Self);
    fn set<'a, V>(&mut self, rhs: &'a V) -> &mut Self where Self: From<&'a V>;
    fn sub<'a, V>(&mut self, rhs: &'a V) -> &mut Self where Self: From<&'a V>;
    fn sub_into<'a, V>(&self, rhs: &'a V, dest: &mut Self) where Self: From<&'a V>;
    fn zero(&mut self) -> &mut Self;
}

pub trait Vector2<C>: Vector<C> {
    fn new(x: C, y: C) -> Self;
}

pub trait Vector3<C>: Vector<C> {
    fn new(x: C, y: C, z: C) -> Self;
    fn cross<'a, V>(&mut self, v: &'a V) -> &mut Self where Self: From<&'a V>;
    fn cross_into<'a, V>(&self, v: &'a V, dest: &mut Self) where Self: From<&'a V>;
}

pub trait Vector4<C>: Vector<C> {
    fn new(x: C, y: C, z: C, w: C) -> Self;
}

pub mod vector2f;
pub mod vector3f;
pub mod vector4f;
<commit_msg>remove todo<commit_after>
// todo: change zero to clear or something like that
pub trait Vector<C>
    where Self: Sized
{
    fn add<'a, V>(&mut self, rhs: &'a V) -> &mut Self where Self: From<&'a V>;
    fn add_into<'a, V>(&self, rhs: &'a V, dest: &mut Self) where Self: From<&'a V>;
    fn angle<'a, V>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn angle_cos<'a, V>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn distance<'a, V>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn distance_sq<'a, V>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn dot<'a, V>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn fma<'a, V>(&mut self, a: &'a V, b: &'a V) -> &mut Self where Self: From<&'a V>;
    fn fma_into<'a, V>(&self, a: &'a V, b: &'a V, dest: &mut Self) where Self: From<&'a V>;
    fn length(&self) -> C;
    fn length_sq(&self) -> C;
    fn lerp<'a, V>(&mut self, other: &'a V, t: C) -> &mut Self where Self: From<&'a V>;
    fn lerp_into<'a, V>(&self, other: &'a V, t: C, dest: &mut Self) where Self: From<&'a V>;
    fn mul<'a, V>(&mut self, rhs: &'a V) -> &mut Self where Self: From<&'a V>;
    fn mul_into<'a, V>(&self, rhs: &'a V, dest: &mut Self) where Self: From<&'a V>;
    fn negate(&mut self) -> &mut Self;
    fn negate_into(&self, dest: &mut Self);
    fn normalize(&mut self) -> &mut Self;
    fn normalize_into(&self, dest: &mut Self);
    fn set<'a, V>(&mut self, rhs: &'a V) -> &mut Self where Self: From<&'a V>;
    fn sub<'a, V>(&mut self, rhs: &'a V) -> &mut Self where Self: From<&'a V>;
    fn sub_into<'a, V>(&self, rhs: &'a V, dest: &mut Self) where Self: From<&'a V>;
    fn zero(&mut self) -> &mut Self;
}

pub trait Vector2<C>: Vector<C> {
    fn new(x: C, y: C) -> Self;
}

pub trait Vector3<C>: Vector<C> {
    fn new(x: C, y: C, z: C) -> Self;
    fn cross<'a, V>(&mut self, v: &'a V) -> &mut Self where Self: From<&'a V>;
    fn cross_into<'a, V>(&self, v: &'a V, dest: &mut Self) where Self: From<&'a V>;
}

pub trait Vector4<C>: Vector<C> {
    fn new(x: C, y: C, z: C, w: C) -> Self;
}

pub mod vector2f;
pub mod vector3f;
pub mod vector4f;
<|endoftext|>


<commit_before>pub mod md5;
pub mod sha1;

pub trait Hasher
{
    /**
     * Reset the hasher's state.
     */
    fn reset(&mut self);

    /**
     * Provide input data.
     */
    fn update(&mut self, data: &[u8]);

    /**
     * Retrieve digest result. The output must be large enough to contains result
     * size (from output_size method).
     */
    fn output(&self, out: &mut [u8]);

    /**
     * Get the output size in bits.
     */
    fn output_size_bits(&self) -> uint;

    /**
     * Get the block size in bits.
     */
    fn block_size_bits(&self) -> uint;

    /**
     * Get the output size in bytes.
     */
    fn output_size(&self) -> uint
    {
        (self.output_size_bits() + 7) / 8
    }

    /**
     * Get the block size in bytes.
     */
    fn block_size(&self) -> uint
    {
        (self.block_size_bits() + 7) / 8
    }

    fn digest(&self) -> ~[u8]
    {
        let size = self.output_size();
        let mut buf = Vec::from_elem(size, 0u8);

        self.output(buf.as_mut_slice());

        buf.as_slice().to_owned()
    }
}

pub trait Hashable {
    /**
     * Feed the value to the hasher passed in parameter.
     */
     fn feed<H: Hasher>(&self, h: &mut H);

    /**
     * Hash the value to ~[u8].
     *
     * Reset the hasher passed in parameter, because we want
     * an empty hasher to get only the value's hash.
     */
    fn to_hash<H: Hasher>(&self, h: &mut H) -> ~[u8]
    {
        h.reset();
        self.feed(h);
        h.digest()
    }
}

impl<'a> Hashable for &'a [u8] {
    fn feed<H: Hasher>(&self, h: &mut H)
    {
        h.update(*self)
    }
}
<commit_msg>Change from ~[T] to Vec<T> for hash mod.<commit_after>pub mod md5;
pub mod sha1;

pub trait Hasher
{
    /**
     * Reset the hasher's state.
     */
    fn reset(&mut self);

    /**
     * Provide input data.
     */
    fn update(&mut self, data: &[u8]);

    /**
     * Retrieve digest result. The output must be large enough to contains result
     * size (from output_size method).
     */
    fn output(&self, out: &mut [u8]);

    /**
     * Get the output size in bits.
     */
    fn output_size_bits(&self) -> uint;

    /**
     * Get the block size in bits.
     */
    fn block_size_bits(&self) -> uint;

    /**
     * Get the output size in bytes.
     */
    fn output_size(&self) -> uint
    {
        (self.output_size_bits() + 7) / 8
    }

    /**
     * Get the block size in bytes.
     */
    fn block_size(&self) -> uint
    {
        (self.block_size_bits() + 7) / 8
    }

    fn digest(&self) -> Vec<u8>
    {
        let size = self.output_size();
        let mut buf = Vec::from_elem(size, 0u8);

        self.output(buf.as_mut_slice());

        buf
    }
}

pub trait Hashable {
    /**
     * Feed the value to the hasher passed in parameter.
     */
     fn feed<H: Hasher>(&self, h: &mut H);

    /**
     * Hash the value to ~[u8].
     *
     * Reset the hasher passed in parameter, because we want
     * an empty hasher to get only the value's hash.
     */
    fn to_hash<H: Hasher>(&self, h: &mut H) -> Vec<u8>
    {
        h.reset();
        self.feed(h);
        h.digest()
    }
}

impl<'a> Hashable for &'a [u8] {
    fn feed<H: Hasher>(&self, h: &mut H)
    {
        h.update(*self)
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::path::Path;
use std::borrow::Borrow;
use std::ops::Deref;

use glob::Paths;
use semver::Version;
use std::fmt::{Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;

use error::{StoreError, StoreErrorKind};
use store::Result;
use store::Store;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId(PathBuf);

impl Into<PathBuf> for StoreId {

    fn into(self) -> PathBuf {
        self.0
    }

}

impl Deref for StoreId {
    type Target = PathBuf;

    fn deref(&self) -> &PathBuf {
        &self.0
    }

}

impl From<PathBuf> for StoreId {

    fn from(pb: PathBuf) -> StoreId {
        StoreId(pb)
    }

}

impl From<String> for StoreId {

    fn from(string: String) -> StoreId {
        StoreId(string.into())
    }

}

impl AsRef<Path> for StoreId {

    fn as_ref(&self) -> &Path {
        self.0.as_ref()
    }

}

impl Borrow<Path> for StoreId {

    fn borrow(&self) -> &Path {
        self.0.borrow()
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> StoreId;
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> StoreId {
        StoreId(self)
    }
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> StoreId {
        self
    }
}

pub fn build_entry_path(store: &Store, path_elem: &str) -> Result<PathBuf> {
    debug!("Checking path element for version");
    if path_elem.split("~").last().map(|v| Version::parse(v).is_err()).unwrap_or(false) {
        debug!("Version cannot be parsed from {:?}", path_elem);
        debug!("Path does not contain version!");
        return Err(StoreError::new(StoreErrorKind::StorePathLacksVersion, None));
    }
    debug!("Version checking succeeded");

    debug!("Building path from {:?}", path_elem);
    let mut path = store.path().clone();

    if path_elem.chars().next() == Some('/') {
        path.push(&path_elem[1..path_elem.len()]);
    } else {
        path.push(path_elem);
    }

    Ok(path)
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr, $version:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use semver::Version;
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let version = Version::parse($version).unwrap();
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(format!("{}~{}",
                                               name,
                                               version));
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> $crate::storeid::StoreId {
                    StoreId::from(self.0)
                }
            }
        }
    )
}

pub struct GlobStoreIdIterator {
    paths: Paths,
}

impl Debug for GlobStoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "GlobStoreIdIterator")
    }

}

impl GlobStoreIdIterator {

    pub fn new(paths: Paths) -> GlobStoreIdIterator {
        GlobStoreIdIterator {
            paths: paths,
        }
    }

}

impl Iterator for GlobStoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.paths.next().and_then(|o| o.ok()).map(|p| StoreId::from(p))
    }

}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test", "0.2.0-alpha+leet1337");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().to_str().unwrap(), "test/test~0.2.0-alpha+leet1337");
    }

}
<commit_msg>Add error printing (debug) in GlobStoreIdIterator helper type<commit_after>use std::path::PathBuf;
use std::path::Path;
use std::borrow::Borrow;
use std::ops::Deref;

use glob::Paths;
use semver::Version;
use std::fmt::{Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;

use error::{StoreError, StoreErrorKind};
use store::Result;
use store::Store;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId(PathBuf);

impl Into<PathBuf> for StoreId {

    fn into(self) -> PathBuf {
        self.0
    }

}

impl Deref for StoreId {
    type Target = PathBuf;

    fn deref(&self) -> &PathBuf {
        &self.0
    }

}

impl From<PathBuf> for StoreId {

    fn from(pb: PathBuf) -> StoreId {
        StoreId(pb)
    }

}

impl From<String> for StoreId {

    fn from(string: String) -> StoreId {
        StoreId(string.into())
    }

}

impl AsRef<Path> for StoreId {

    fn as_ref(&self) -> &Path {
        self.0.as_ref()
    }

}

impl Borrow<Path> for StoreId {

    fn borrow(&self) -> &Path {
        self.0.borrow()
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> StoreId;
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> StoreId {
        StoreId(self)
    }
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> StoreId {
        self
    }
}

pub fn build_entry_path(store: &Store, path_elem: &str) -> Result<PathBuf> {
    debug!("Checking path element for version");
    if path_elem.split("~").last().map(|v| Version::parse(v).is_err()).unwrap_or(false) {
        debug!("Version cannot be parsed from {:?}", path_elem);
        debug!("Path does not contain version!");
        return Err(StoreError::new(StoreErrorKind::StorePathLacksVersion, None));
    }
    debug!("Version checking succeeded");

    debug!("Building path from {:?}", path_elem);
    let mut path = store.path().clone();

    if path_elem.chars().next() == Some('/') {
        path.push(&path_elem[1..path_elem.len()]);
    } else {
        path.push(path_elem);
    }

    Ok(path)
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr, $version:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use semver::Version;
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let version = Version::parse($version).unwrap();
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(format!("{}~{}",
                                               name,
                                               version));
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> $crate::storeid::StoreId {
                    StoreId::from(self.0)
                }
            }
        }
    )
}

pub struct GlobStoreIdIterator {
    paths: Paths,
}

impl Debug for GlobStoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "GlobStoreIdIterator")
    }

}

impl GlobStoreIdIterator {

    pub fn new(paths: Paths) -> GlobStoreIdIterator {
        GlobStoreIdIterator {
            paths: paths,
        }
    }

}

impl Iterator for GlobStoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.paths.next().and_then(|o| {
            match o {
                Ok(o) => Some(o),
                Err(e) => {
                    debug!("GlobStoreIdIterator error: {:?}", e);
                    None
                },
            }
        }).map(|p| StoreId::from(p))
    }

}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test", "0.2.0-alpha+leet1337");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().to_str().unwrap(), "test/test~0.2.0-alpha+leet1337");
    }

}
<|endoftext|>