<commit_before>#![cfg(feature = "full")]

#[macro_use]
extern crate quote;
extern crate syn;
extern crate syntex_pos;
extern crate syntex_syntax;
extern crate time;
extern crate walkdir;

use syntex_pos::Span;
use syntex_syntax::ast;
use syntex_syntax::parse::{self, ParseSess, PResult};
use time::PreciseTime;

use std::fs::File;
use std::io::{self, Read, Write};

macro_rules! errorf {
    ($($tt:tt)*) => {
        write!(io::stderr(), $($tt)*).unwrap();
    };
}

#[test]
fn test_round_trip() {
    let mut failed = 0;

    for entry in walkdir::WalkDir::new("tests/cases").into_iter() {
        let entry = entry.unwrap();

        let path = entry.path();
        if path.extension().map(|e| e != "rs").unwrap_or(true) {
            continue;
        }
        errorf!("=== {}: ", path.display());

        let mut file = File::open(path).unwrap();
        let mut content = String::new();
        file.read_to_string(&mut content).unwrap();

        let start = PreciseTime::now();
        let (krate, elapsed) = match syn::parse_crate(&content) {
            Ok(krate) => (krate, start.to(PreciseTime::now())),
            Err(msg) => {
                errorf!("syn failed to parse\n{}\n", msg);
                failed += 1;
                continue;
            }
        };
        let back = quote!(#krate).to_string();

        let sess = ParseSess::new();
        let before = match syntex_parse(content, &sess) {
            Ok(before) => before,
            Err(mut diagnostic) => {
                diagnostic.cancel();
                if diagnostic.message.starts_with("file not found for module") {
                    errorf!("ignore\n");
                    continue;
                } else {
                    panic!(diagnostic.message.clone());
                }
            }
        };
        let after = match syntex_parse(back, &sess) {
            Ok(after) => after,
            Err(mut diagnostic) => {
                errorf!("syntex failed to parse");
                diagnostic.emit();
                failed += 1;
                continue;
            }
        };

        if before == after {
            errorf!("pass in {}ms\n", elapsed.num_milliseconds());
        } else {
            errorf!("FAIL\nbefore: {:?}\nafter: {:?}\n", before, after);
            failed += 1;
        }
    }

    if failed > 0 {
        panic!("{} failures", failed);
    }
}

fn syntex_parse<'a>(content: String, sess: &'a ParseSess) -> PResult<'a, ast::Crate> {
    let name = "test_round_trip".to_string();
    let cfg = Vec::new();
    parse::parse_crate_from_source_str(name, content, cfg, sess).map(respan_crate)
}

fn respan_crate(krate: ast::Crate) -> ast::Crate {
    use std::rc::Rc;
    use syntex_syntax::ast::{Attribute, Expr, ExprKind, Field, FnDecl, FunctionRetTy, ImplItem,
                             ImplItemKind, ItemKind, Mac, MethodSig, TraitItem, TraitItemKind,
                             TyParam};
    use syntex_syntax::codemap::{self, Spanned};
    use syntex_syntax::fold::{self, Folder};
    use syntex_syntax::parse::token::{Lit, Token, intern};
    use syntex_syntax::ptr::P;
    use syntex_syntax::tokenstream::{Delimited, SequenceRepetition, TokenTree};
    use syntex_syntax::util::move_map::MoveMap;
    use syntex_syntax::util::small_vector::SmallVector;

    struct Respanner;

    impl Respanner {
        fn fold_spanned<T>(&mut self, spanned: Spanned<T>) -> Spanned<T> {
            codemap::respan(self.new_span(spanned.span), spanned.node)
        }

        fn fold_lit(&mut self, l: Lit) -> Lit {
            match l {
                Lit::Integer(repr) => {
                    Lit::Integer(intern(&repr.to_string().replace("_", "")))
                }
                Lit::Str_(_) => {
                    // Give up on comparing strings because there are so many
                    // equivalent representations of the same string; they are
                    // tested elsewhere
                    Lit::Str_(intern(""))
                }
                Lit::Float(repr) => {
                    Lit::Float(intern(&repr.to_string().replace("_", "")))
                }
                _ => l,
            }
        }
    }

    impl Folder for Respanner {
        fn new_span(&mut self, _: Span) -> Span {
            syntex_pos::DUMMY_SP
        }

        fn fold_item_kind(&mut self, i: ItemKind) -> ItemKind {
            match i {
                ItemKind::Fn(decl, unsafety, constness, abi, generics, body) => {
                    let generics = self.fold_generics(generics);
                    let decl = self.fold_fn_decl(decl);
                    let body = self.fold_block(body);
                    // default fold_item_kind does not fold this span
                    let constness = self.fold_spanned(constness);
                    ItemKind::Fn(decl, unsafety, constness, abi, generics, body)
                }
                _ => fold::noop_fold_item_kind(i, self),
            }
        }

        fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
            e.map(|e| {
                let folded = fold::noop_fold_expr(e, self);
                Expr {
                    node: match folded.node {
                        ExprKind::Lit(l) => {
                            // default fold_expr does not fold lits
                            ExprKind::Lit(l.map(|l| self.fold_spanned(l)))
                        }
                        ExprKind::Binary(op, lhs, rhs) => {
                            // default fold_expr does not fold the op span
                            ExprKind::Binary(self.fold_spanned(op),
                                             self.fold_expr(lhs),
                                             self.fold_expr(rhs))
                        }
                        ExprKind::AssignOp(op, lhs, rhs) => {
                            // default fold_expr does not fold the op span
                            ExprKind::AssignOp(self.fold_spanned(op),
                                               self.fold_expr(lhs),
                                               self.fold_expr(rhs))
                        }
                        other => other,
                    },
                    ..folded
                }
            })
        }

        fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
            TyParam {
                // default fold_ty_param does not fold the span
                span: self.new_span(tp.span),
                ..fold::noop_fold_ty_param(tp, self)
            }
        }

        fn fold_fn_decl(&mut self, decl: P<FnDecl>) -> P<FnDecl> {
            decl.map(|FnDecl { inputs, output, variadic }| {
                FnDecl {
                    inputs: inputs.move_map(|x| self.fold_arg(x)),
                    output: match output {
                        FunctionRetTy::Ty(ty) => FunctionRetTy::Ty(self.fold_ty(ty)),
                        // default fold_fn_decl does not fold this span
                        FunctionRetTy::Default(span) => FunctionRetTy::Default(self.new_span(span)),
                    },
                    variadic: variadic,
                }
            })
        }

        fn fold_field(&mut self, field: Field) -> Field {
            Field {
                ident: codemap::respan(// default fold_field does not fold this span
                                       self.new_span(field.ident.span),
                                       self.fold_ident(field.ident.node)),
                expr: self.fold_expr(field.expr),
                span: self.new_span(field.span),
            }
        }

        fn fold_trait_item(&mut self, i: TraitItem) -> SmallVector<TraitItem> {
            let noop = fold::noop_fold_trait_item(i, self).expect_one("");
            SmallVector::one(TraitItem {
                node: match noop.node {
                    TraitItemKind::Method(sig, body) => {
                        TraitItemKind::Method(MethodSig {
                                                  constness: self.fold_spanned(sig.constness),
                                                  ..sig
                                              },
                                              body)
                    }
                    node => node,
                },
                ..noop
            })
        }

        fn fold_impl_item(&mut self, i: ImplItem) -> SmallVector<ImplItem> {
            let noop = fold::noop_fold_impl_item(i, self).expect_one("");
            SmallVector::one(ImplItem {
                node: match noop.node {
                    ImplItemKind::Method(sig, body) => {
                        ImplItemKind::Method(MethodSig {
                                                 constness: self.fold_spanned(sig.constness),
                                                 ..sig
                                             },
                                             body)
                    }
                    node => node,
                },
                ..noop
            })
        }

        fn fold_attribute(&mut self, mut at: Attribute) -> Option<Attribute> {
            at.node.id.0 = 0;
            fold::noop_fold_attribute(at, self)
        }

        fn fold_mac(&mut self, mac: Mac) -> Mac {
            fold::noop_fold_mac(mac, self)
        }

        fn fold_tt(&mut self, tt: &TokenTree) -> TokenTree {
            match *tt {
                TokenTree::Token(span, ref tok) => {
                    TokenTree::Token(self.new_span(span), self.fold_token(tok.clone()))
                }
                TokenTree::Delimited(span, ref delimed) => {
                    TokenTree::Delimited(self.new_span(span),
                                         Rc::new(Delimited {
                                             delim: delimed.delim,
                                             open_span: self.new_span(delimed.open_span),
                                             tts: self.fold_tts(&delimed.tts),
                                             close_span: self.new_span(delimed.close_span),
                                         }))
                }
                TokenTree::Sequence(span, ref seq) => {
                    TokenTree::Sequence(self.new_span(span),
                                        Rc::new(SequenceRepetition {
                                            tts: self.fold_tts(&seq.tts),
                                            separator: seq.separator
                                                .clone()
                                                .map(|tok| self.fold_token(tok)),
                                            ..**seq
                                        }))
                }
            }
        }

        fn fold_token(&mut self, t: Token) -> Token {
            match t {
                // default fold_token does not fold literals
                Token::Literal(lit, repr) => Token::Literal(self.fold_lit(lit), repr),
                Token::Ident(id) => Token::Ident(self.fold_ident(id)),
                Token::Lifetime(id) => Token::Lifetime(self.fold_ident(id)),
                Token::Interpolated(nt) => Token::Interpolated(self.fold_interpolated(nt)),
                Token::SubstNt(ident) => Token::SubstNt(self.fold_ident(ident)),
                Token::MatchNt(name, kind) => {
                    Token::MatchNt(self.fold_ident(name), self.fold_ident(kind))
                }
                _ => t,
            }
        }
    }

    Respanner.fold_crate(krate)
}
<commit_msg>Fold away spans inside of meta items<commit_after>#![cfg(feature = "full")]

#[macro_use]
extern crate quote;
extern crate syn;
extern crate syntex_pos;
extern crate syntex_syntax;
extern crate time;
extern crate walkdir;

use syntex_pos::Span;
use syntex_syntax::ast;
use syntex_syntax::parse::{self, ParseSess, PResult};
use time::PreciseTime;

use std::fs::File;
use std::io::{self, Read, Write};

macro_rules! errorf {
    ($($tt:tt)*) => {
        write!(io::stderr(), $($tt)*).unwrap();
    };
}

#[test]
fn test_round_trip() {
    let mut failed = 0;

    for entry in walkdir::WalkDir::new("tests/cases").into_iter() {
        let entry = entry.unwrap();

        let path = entry.path();
        if path.extension().map(|e| e != "rs").unwrap_or(true) {
            continue;
        }
        errorf!("=== {}: ", path.display());

        let mut file = File::open(path).unwrap();
        let mut content = String::new();
        file.read_to_string(&mut content).unwrap();

        let start = PreciseTime::now();
        let (krate, elapsed) = match syn::parse_crate(&content) {
            Ok(krate) => (krate, start.to(PreciseTime::now())),
            Err(msg) => {
                errorf!("syn failed to parse\n{}\n", msg);
                failed += 1;
                continue;
            }
        };
        let back = quote!(#krate).to_string();

        let sess = ParseSess::new();
        let before = match syntex_parse(content, &sess) {
            Ok(before) => before,
            Err(mut diagnostic) => {
                diagnostic.cancel();
                if diagnostic.message.starts_with("file not found for module") {
                    errorf!("ignore\n");
                    continue;
                } else {
                    panic!(diagnostic.message.clone());
                }
            }
        };
        let after = match syntex_parse(back, &sess) {
            Ok(after) => after,
            Err(mut diagnostic) => {
                errorf!("syntex failed to parse");
                diagnostic.emit();
                failed += 1;
                continue;
            }
        };

        if before == after {
            errorf!("pass in {}ms\n", elapsed.num_milliseconds());
        } else {
            errorf!("FAIL\nbefore: {:?}\nafter: {:?}\n", before, after);
            failed += 1;
        }
    }

    if failed > 0 {
        panic!("{} failures", failed);
    }
}

fn syntex_parse<'a>(content: String, sess: &'a ParseSess) -> PResult<'a, ast::Crate> {
    let name = "test_round_trip".to_string();
    let cfg = Vec::new();
    parse::parse_crate_from_source_str(name, content, cfg, sess).map(respan_crate)
}

fn respan_crate(krate: ast::Crate) -> ast::Crate {
    use std::rc::Rc;
    use syntex_syntax::ast::{Attribute, Expr, ExprKind, Field, FnDecl, FunctionRetTy, ImplItem,
                             ImplItemKind, ItemKind, Mac, MetaItem, MetaItemKind, MethodSig,
                             NestedMetaItem, NestedMetaItemKind, TraitItem, TraitItemKind,
                             TyParam};
    use syntex_syntax::codemap::{self, Spanned};
    use syntex_syntax::fold::{self, Folder};
    use syntex_syntax::parse::token::{Lit, Token, intern};
    use syntex_syntax::ptr::P;
    use syntex_syntax::tokenstream::{Delimited, SequenceRepetition, TokenTree};
    use syntex_syntax::util::move_map::MoveMap;
    use syntex_syntax::util::small_vector::SmallVector;

    struct Respanner;

    impl Respanner {
        fn fold_spanned<T>(&mut self, spanned: Spanned<T>) -> Spanned<T> {
            codemap::respan(self.new_span(spanned.span), spanned.node)
        }

        fn fold_lit(&mut self, l: Lit) -> Lit {
            match l {
                Lit::Integer(repr) => {
                    Lit::Integer(intern(&repr.to_string().replace("_", "")))
                }
                Lit::Str_(_) => {
                    // Give up on comparing strings because there are so many
                    // equivalent representations of the same string; they are
                    // tested elsewhere
                    Lit::Str_(intern(""))
                }
                Lit::Float(repr) => {
                    Lit::Float(intern(&repr.to_string().replace("_", "")))
                }
                _ => l,
            }
        }
    }

    impl Folder for Respanner {
        fn new_span(&mut self, _: Span) -> Span {
            syntex_pos::DUMMY_SP
        }

        fn fold_item_kind(&mut self, i: ItemKind) -> ItemKind {
            match i {
                ItemKind::Fn(decl, unsafety, constness, abi, generics, body) => {
                    let generics = self.fold_generics(generics);
                    let decl = self.fold_fn_decl(decl);
                    let body = self.fold_block(body);
                    // default fold_item_kind does not fold this span
                    let constness = self.fold_spanned(constness);
                    ItemKind::Fn(decl, unsafety, constness, abi, generics, body)
                }
                _ => fold::noop_fold_item_kind(i, self),
            }
        }

        fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
            e.map(|e| {
                let folded = fold::noop_fold_expr(e, self);
                Expr {
                    node: match folded.node {
                        ExprKind::Lit(l) => {
                            // default fold_expr does not fold lits
                            ExprKind::Lit(l.map(|l| self.fold_spanned(l)))
                        }
                        ExprKind::Binary(op, lhs, rhs) => {
                            // default fold_expr does not fold the op span
                            ExprKind::Binary(self.fold_spanned(op),
                                             self.fold_expr(lhs),
                                             self.fold_expr(rhs))
                        }
                        ExprKind::AssignOp(op, lhs, rhs) => {
                            // default fold_expr does not fold the op span
                            ExprKind::AssignOp(self.fold_spanned(op),
                                               self.fold_expr(lhs),
                                               self.fold_expr(rhs))
                        }
                        other => other,
                    },
                    ..folded
                }
            })
        }

        fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
            TyParam {
                // default fold_ty_param does not fold the span
                span: self.new_span(tp.span),
                ..fold::noop_fold_ty_param(tp, self)
            }
        }

        fn fold_fn_decl(&mut self, decl: P<FnDecl>) -> P<FnDecl> {
            decl.map(|FnDecl { inputs, output, variadic }| {
                FnDecl {
                    inputs: inputs.move_map(|x| self.fold_arg(x)),
                    output: match output {
                        FunctionRetTy::Ty(ty) => FunctionRetTy::Ty(self.fold_ty(ty)),
                        // default fold_fn_decl does not fold this span
                        FunctionRetTy::Default(span) => FunctionRetTy::Default(self.new_span(span)),
                    },
                    variadic: variadic,
                }
            })
        }

        fn fold_field(&mut self, field: Field) -> Field {
            Field {
                ident: codemap::respan(// default fold_field does not fold this span
                                       self.new_span(field.ident.span),
                                       self.fold_ident(field.ident.node)),
                expr: self.fold_expr(field.expr),
                span: self.new_span(field.span),
            }
        }

        fn fold_trait_item(&mut self, i: TraitItem) -> SmallVector<TraitItem> {
            let noop = fold::noop_fold_trait_item(i, self).expect_one("");
            SmallVector::one(TraitItem {
                node: match noop.node {
                    TraitItemKind::Method(sig, body) => {
                        TraitItemKind::Method(MethodSig {
                                                  constness: self.fold_spanned(sig.constness),
                                                  ..sig
                                              },
                                              body)
                    }
                    node => node,
                },
                ..noop
            })
        }

        fn fold_impl_item(&mut self, i: ImplItem) -> SmallVector<ImplItem> {
            let noop = fold::noop_fold_impl_item(i, self).expect_one("");
            SmallVector::one(ImplItem {
                node: match noop.node {
                    ImplItemKind::Method(sig, body) => {
                        ImplItemKind::Method(MethodSig {
                                                 constness: self.fold_spanned(sig.constness),
                                                 ..sig
                                             },
                                             body)
                    }
                    node => node,
                },
                ..noop
            })
        }

        fn fold_attribute(&mut self, mut at: Attribute) -> Option<Attribute> {
            at.node.id.0 = 0;
            fold::noop_fold_attribute(at, self)
        }

        fn fold_meta_item(&mut self, meta_item: P<MetaItem>) -> P<MetaItem> {
            meta_item.map(|Spanned {node, span}| Spanned {
                node: match node {
                    MetaItemKind::Word(id) => MetaItemKind::Word(id),
                    MetaItemKind::List(id, mis) => {
                        MetaItemKind::List(id, mis.move_map(|e| self.fold_meta_list_item(e)))
                    }
                    // default fold_meta_item does not fold the value span
                    MetaItemKind::NameValue(id, lit) => MetaItemKind::NameValue(id, self.fold_spanned(lit))
                },
                span: self.new_span(span)
            })
        }

        fn fold_meta_list_item(&mut self, list_item: NestedMetaItem) -> NestedMetaItem {
            Spanned {
                node: match list_item.node {
                    NestedMetaItemKind::MetaItem(mi) =>  {
                        NestedMetaItemKind::MetaItem(self.fold_meta_item(mi))
                    },
                    // default fold_meta_list_item does not fold the span
                    NestedMetaItemKind::Literal(lit) => NestedMetaItemKind::Literal(self.fold_spanned(lit))
                },
                span: self.new_span(list_item.span)
            }
        }

        fn fold_mac(&mut self, mac: Mac) -> Mac {
            fold::noop_fold_mac(mac, self)
        }

        fn fold_tt(&mut self, tt: &TokenTree) -> TokenTree {
            match *tt {
                TokenTree::Token(span, ref tok) => {
                    TokenTree::Token(self.new_span(span), self.fold_token(tok.clone()))
                }
                TokenTree::Delimited(span, ref delimed) => {
                    TokenTree::Delimited(self.new_span(span),
                                         Rc::new(Delimited {
                                             delim: delimed.delim,
                                             open_span: self.new_span(delimed.open_span),
                                             tts: self.fold_tts(&delimed.tts),
                                             close_span: self.new_span(delimed.close_span),
                                         }))
                }
                TokenTree::Sequence(span, ref seq) => {
                    TokenTree::Sequence(self.new_span(span),
                                        Rc::new(SequenceRepetition {
                                            tts: self.fold_tts(&seq.tts),
                                            separator: seq.separator
                                                .clone()
                                                .map(|tok| self.fold_token(tok)),
                                            ..**seq
                                        }))
                }
            }
        }

        fn fold_token(&mut self, t: Token) -> Token {
            match t {
                // default fold_token does not fold literals
                Token::Literal(lit, repr) => Token::Literal(self.fold_lit(lit), repr),
                Token::Ident(id) => Token::Ident(self.fold_ident(id)),
                Token::Lifetime(id) => Token::Lifetime(self.fold_ident(id)),
                Token::Interpolated(nt) => Token::Interpolated(self.fold_interpolated(nt)),
                Token::SubstNt(ident) => Token::SubstNt(self.fold_ident(ident)),
                Token::MatchNt(name, kind) => {
                    Token::MatchNt(self.fold_ident(name), self.fold_ident(kind))
                }
                _ => t,
            }
        }
    }

    Respanner.fold_crate(krate)
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Date_format

extern crate chrono;
use chrono::*;
fn main(){
    let now : DateTime<UTC> = UTC::now();
    println!("{}", now.format("%Y-%m-%d").to_string());
    println!("{}", now.format("%A, %B %d, %Y").to_string());
}
<commit_msg>whitespace fix<commit_after>// http://rosettacode.org/wiki/Date_format

extern crate chrono;
use chrono::*;
fn main(){
    let now : DateTime<UTC> = UTC::now();
    println!("{}", now.format("%Y-%m-%d").to_string());
    println!("{}", now.format("%A, %B %d, %Y").to_string());
}
<|endoftext|>


<commit_before>extern crate dbus;
use self::dbus::ConnectionItem;

use std::vec::Vec;

pub struct SignalInfo {
    pub path: Option<String>,
    pub object: Option<String>,
    pub member: Option<String>,
}

pub type CallbackMap<Ctx> = Vec<(SignalInfo, fn(&SignalInfo, &Ctx) -> ())>;

fn cmp_option<T: Eq>(a: &Option<T>, b: &Option<T>) -> bool {
    a.is_none() || a == b
}

fn match_info(info: &SignalInfo, expect: &SignalInfo) -> bool {
    cmp_option(&expect.path, &info.path) &&
    cmp_option(&expect.object, &info.object) &&
    cmp_option(&expect.member, &info.member)
}

pub fn match_signal<Ctx>(item: ConnectionItem, map: &CallbackMap<Ctx>, ctx: &Ctx) -> () {
    match item {
        ConnectionItem::Signal(s) => {
            let (_, p, o, m) = s.headers();
            let info = SignalInfo { path: p, object: o, member: m };

            for cb_item in (*map).iter() {
                let (ref expect, ref cb) = *cb_item;

                if match_info(&info, expect) {
                    cb(&info, ctx);
                }
            }
        },
        _ => ()
    }
}

pub fn make_signal_info(path: &str, object: &str, member: &str) -> SignalInfo {
    SignalInfo {
        path: Some(path.to_string()),
        object: Some(object.to_string()),
        member: Some(member.to_string()),
    }
}
<commit_msg>dbus_listen: also look for method calls<commit_after>extern crate dbus;
use self::dbus::{ConnectionItem, Message};

use std::vec::Vec;

pub struct SignalInfo {
    pub path: Option<String>,
    pub object: Option<String>,
    pub member: Option<String>,
}

pub type CallbackMap<Ctx> = Vec<(SignalInfo, fn(&SignalInfo, &Ctx) -> ())>;

fn cmp_option<T: Eq>(a: &Option<T>, b: &Option<T>) -> bool {
    a.is_none() || a == b
}

fn match_info(info: &SignalInfo, expect: &SignalInfo) -> bool {
    cmp_option(&expect.path, &info.path) &&
    cmp_option(&expect.object, &info.object) &&
    cmp_option(&expect.member, &info.member)
}

fn handle_message<Ctx>(msg: Message, map: &CallbackMap<Ctx>, ctx: &Ctx) -> () {
    let (_, p, o, m) = msg.headers();
    let info = SignalInfo { path: p, object: o, member: m };

    for cb_item in (*map).iter() {
        let (ref expect, ref cb) = *cb_item;

        if match_info(&info, expect) {
            cb(&info, ctx);
        }
    }
}

pub fn match_signal<Ctx>(item: ConnectionItem, map: &CallbackMap<Ctx>, ctx: &Ctx) -> () {
    match item {
        ConnectionItem::MethodCall(m) => handle_message(m, map, ctx),
        ConnectionItem::Signal(s) => handle_message(s, map, ctx),
        _ => ()
    }
}

pub fn make_signal_info(path: &str, object: &str, member: &str) -> SignalInfo {
    SignalInfo {
        path: Some(path.to_string()),
        object: Some(object.to_string()),
        member: Some(member.to_string()),
    }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::fmt;

use log::trace;

use rustc_span::DUMMY_SP;

use crate::*;

/// Details of premature program termination.
pub enum TerminationInfo {
    Exit(i64),
    Abort(Option<String>),
    UnsupportedInIsolation(String),
    ExperimentalUb { msg: String, url: String },
    Deadlock,
}

impl fmt::Debug for TerminationInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use TerminationInfo::*;
        match self {
            Exit(code) =>
                write!(f, "the evaluated program completed with exit code {}", code),
            Abort(None) =>
                write!(f, "the evaluated program aborted execution"),
            Abort(Some(msg)) =>
                write!(f, "the evaluated program aborted execution: {}", msg),
            UnsupportedInIsolation(msg) =>
                write!(f, "{}", msg),
            ExperimentalUb { msg, .. } =>
                write!(f, "{}", msg),
            Deadlock =>
                write!(f, "the evaluated program deadlocked"),
        }
    }
}

impl MachineStopType for TerminationInfo {}

/// Miri specific diagnostics
pub enum NonHaltingDiagnostic {
    PoppedTrackedPointerTag(Item),
    CreatedAlloc(AllocId),
    FreedAlloc(AllocId),
}

/// Emit a custom diagnostic without going through the miri-engine machinery
pub fn report_error<'tcx, 'mir>(
    ecx: &InterpCx<'mir, 'tcx, Evaluator<'mir, 'tcx>>,
    mut e: InterpErrorInfo<'tcx>,
) -> Option<i64> {
    use InterpError::*;

    let (title, helps) = match &e.kind {
        MachineStop(info) => {
            let info = info.downcast_ref::<TerminationInfo>().expect("invalid MachineStop payload");
            use TerminationInfo::*;
            let title = match info {
                Exit(code) => return Some(*code),
                Abort(_) =>
                    "abnormal termination",
                UnsupportedInIsolation(_) =>
                    "unsupported operation",
                ExperimentalUb { .. } =>
                    "Undefined Behavior",
                Deadlock => "deadlock",
            };
            let helps = match info {
                UnsupportedInIsolation(_) =>
                    vec![format!("pass the flag `-Zmiri-disable-isolation` to disable isolation")],
                ExperimentalUb { url, .. } =>
                    vec![
                        format!("this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental"),
                        format!("see {} for further information", url),
                    ],
                _ => vec![],
            };
            (title, helps)
        }
        _ => {
            let title = match e.kind {
                Unsupported(_) =>
                    "unsupported operation",
                UndefinedBehavior(_) =>
                    "Undefined Behavior",
                ResourceExhaustion(_) =>
                    "resource exhaustion",
                _ =>
                    bug!("This error should be impossible in Miri: {}", e),
            };
            let helps = match e.kind {
                Unsupported(UnsupportedOpInfo::NoMirFor(..)) =>
                    vec![format!("make sure to use a Miri sysroot, which you can prepare with `cargo miri setup`")],
                Unsupported(UnsupportedOpInfo::ReadBytesAsPointer) =>
                    panic!("`ReadBytesAsPointer` cannot be raised by Miri"),
                Unsupported(_) =>
                    vec![format!("this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support")],
                UndefinedBehavior(UndefinedBehaviorInfo::AlignmentCheckFailed { .. }) =>
                    vec![
                        format!("this usually indicates that your program performed an invalid operation and caused Undefined Behavior"),
                        format!("but alignment errors can also be false positives, see https://github.com/rust-lang/miri/issues/1074"),
                        format!("you can disable the alignment check with `-Zmiri-disable-alignment-check`, but that could hide true bugs")
                    ],
                UndefinedBehavior(_) =>
                    vec![
                        format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"),
                        format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information"),
                    ],
                _ => vec![],
            };
            (title, helps)
        }
    };

    e.print_backtrace();
    let msg = e.to_string();
    let result = report_msg(ecx, &format!("{}: {}", title, msg), msg, helps, true);

    if let UndefinedBehavior(UndefinedBehaviorInfo::InvalidUndefBytes(Some(ptr))) = e.kind {
        ecx.memory.dump_alloc(ptr.alloc_id);
    }

    result
}

/// Report an error or note (depending on the `error` argument) at the current frame's current statement.
/// Also emits a full stacktrace of the interpreter stack.
fn report_msg<'tcx, 'mir>(
    ecx: &InterpCx<'mir, 'tcx, Evaluator<'mir, 'tcx>>,
    title: &str,
    span_msg: String,
    mut helps: Vec<String>,
    error: bool,
) -> Option<i64> {
    let span = if let Some(frame) = ecx.machine.stack.last() {
        frame.current_source_info().unwrap().span
    } else {
        DUMMY_SP
    };
    let mut err = if error {
        ecx.tcx.sess.struct_span_err(span, title)
    } else {
        ecx.tcx.sess.diagnostic().span_note_diag(span, title)
    };
    err.span_label(span, span_msg);
    if !helps.is_empty() {
        // Add visual separator before backtrace.
        helps.last_mut().unwrap().push_str("\n");
        for help in helps {
            err.help(&help);
        }
    }
    // Add backtrace
    let frames = ecx.generate_stacktrace();
    for (idx, frame_info) in frames.iter().enumerate() {
        let is_local = frame_info.instance.def_id().is_local();
        // No span for non-local frames and the first frame (which is the error site).
        if is_local && idx > 0 {
            err.span_note(frame_info.span, &frame_info.to_string());
        } else {
            err.note(&frame_info.to_string());
        }
    }

    err.emit();

    for (i, frame) in ecx.machine.stack.iter().enumerate() {
        trace!("-------------------");
        trace!("Frame {}", i);
        trace!("    return: {:?}", frame.return_place.map(|p| *p));
        for (i, local) in frame.locals.iter().enumerate() {
            trace!("    local {}: {:?}", i, local.value);
        }
    }
    // Let the reported error determine the return code.
    return None;
}

thread_local! {
    static DIAGNOSTICS: RefCell<Vec<NonHaltingDiagnostic>> = RefCell::new(Vec::new());
}

/// Schedule a diagnostic for emitting. This function works even if you have no `InterpCx` available.
/// The diagnostic will be emitted after the current interpreter step is finished.
pub fn register_diagnostic(e: NonHaltingDiagnostic) {
    DIAGNOSTICS.with(|diagnostics| diagnostics.borrow_mut().push(e));
}

impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    /// Emit all diagnostics that were registed with `register_diagnostics`
    fn process_diagnostics(&self) {
        let this = self.eval_context_ref();
        DIAGNOSTICS.with(|diagnostics| {
            for e in diagnostics.borrow_mut().drain(..) {
                use NonHaltingDiagnostic::*;
                let msg = match e {
                    PoppedTrackedPointerTag(item) =>
                        format!("popped tracked tag for item {:?}", item),
                    CreatedAlloc(AllocId(id)) =>
                        format!("created allocation with id {}", id),
                    FreedAlloc(AllocId(id)) =>
                        format!("freed allocation with id {}", id),
                };
                report_msg(this, "tracking was triggered", msg, vec![], false);
            }
        });
    }
}
<commit_msg>Add message before dumping alloc<commit_after>use std::cell::RefCell;
use std::fmt;

use log::trace;

use rustc_span::DUMMY_SP;

use crate::*;

/// Details of premature program termination.
pub enum TerminationInfo {
    Exit(i64),
    Abort(Option<String>),
    UnsupportedInIsolation(String),
    ExperimentalUb { msg: String, url: String },
    Deadlock,
}

impl fmt::Debug for TerminationInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use TerminationInfo::*;
        match self {
            Exit(code) =>
                write!(f, "the evaluated program completed with exit code {}", code),
            Abort(None) =>
                write!(f, "the evaluated program aborted execution"),
            Abort(Some(msg)) =>
                write!(f, "the evaluated program aborted execution: {}", msg),
            UnsupportedInIsolation(msg) =>
                write!(f, "{}", msg),
            ExperimentalUb { msg, .. } =>
                write!(f, "{}", msg),
            Deadlock =>
                write!(f, "the evaluated program deadlocked"),
        }
    }
}

impl MachineStopType for TerminationInfo {}

/// Miri specific diagnostics
pub enum NonHaltingDiagnostic {
    PoppedTrackedPointerTag(Item),
    CreatedAlloc(AllocId),
    FreedAlloc(AllocId),
}

/// Emit a custom diagnostic without going through the miri-engine machinery
pub fn report_error<'tcx, 'mir>(
    ecx: &InterpCx<'mir, 'tcx, Evaluator<'mir, 'tcx>>,
    mut e: InterpErrorInfo<'tcx>,
) -> Option<i64> {
    use InterpError::*;

    let (title, helps) = match &e.kind {
        MachineStop(info) => {
            let info = info.downcast_ref::<TerminationInfo>().expect("invalid MachineStop payload");
            use TerminationInfo::*;
            let title = match info {
                Exit(code) => return Some(*code),
                Abort(_) =>
                    "abnormal termination",
                UnsupportedInIsolation(_) =>
                    "unsupported operation",
                ExperimentalUb { .. } =>
                    "Undefined Behavior",
                Deadlock => "deadlock",
            };
            let helps = match info {
                UnsupportedInIsolation(_) =>
                    vec![format!("pass the flag `-Zmiri-disable-isolation` to disable isolation")],
                ExperimentalUb { url, .. } =>
                    vec![
                        format!("this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental"),
                        format!("see {} for further information", url),
                    ],
                _ => vec![],
            };
            (title, helps)
        }
        _ => {
            let title = match e.kind {
                Unsupported(_) =>
                    "unsupported operation",
                UndefinedBehavior(_) =>
                    "Undefined Behavior",
                ResourceExhaustion(_) =>
                    "resource exhaustion",
                _ =>
                    bug!("This error should be impossible in Miri: {}", e),
            };
            let helps = match e.kind {
                Unsupported(UnsupportedOpInfo::NoMirFor(..)) =>
                    vec![format!("make sure to use a Miri sysroot, which you can prepare with `cargo miri setup`")],
                Unsupported(UnsupportedOpInfo::ReadBytesAsPointer) =>
                    panic!("`ReadBytesAsPointer` cannot be raised by Miri"),
                Unsupported(_) =>
                    vec![format!("this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support")],
                UndefinedBehavior(UndefinedBehaviorInfo::AlignmentCheckFailed { .. }) =>
                    vec![
                        format!("this usually indicates that your program performed an invalid operation and caused Undefined Behavior"),
                        format!("but alignment errors can also be false positives, see https://github.com/rust-lang/miri/issues/1074"),
                        format!("you can disable the alignment check with `-Zmiri-disable-alignment-check`, but that could hide true bugs")
                    ],
                UndefinedBehavior(_) =>
                    vec![
                        format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"),
                        format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information"),
                    ],
                _ => vec![],
            };
            (title, helps)
        }
    };

    e.print_backtrace();
    let msg = e.to_string();
    let result = report_msg(ecx, &format!("{}: {}", title, msg), msg, helps, true);

    if let UndefinedBehavior(UndefinedBehaviorInfo::InvalidUndefBytes(Some(ptr))) = e.kind {
        eprintln!(
            "Uninitialized read occurred at offset 0x{:x} into this allocation:",
            ptr.offset.bytes(),
        );
        ecx.memory.dump_alloc(ptr.alloc_id);
        eprintln!();
    }

    result
}

/// Report an error or note (depending on the `error` argument) at the current frame's current statement.
/// Also emits a full stacktrace of the interpreter stack.
fn report_msg<'tcx, 'mir>(
    ecx: &InterpCx<'mir, 'tcx, Evaluator<'mir, 'tcx>>,
    title: &str,
    span_msg: String,
    mut helps: Vec<String>,
    error: bool,
) -> Option<i64> {
    let span = if let Some(frame) = ecx.machine.stack.last() {
        frame.current_source_info().unwrap().span
    } else {
        DUMMY_SP
    };
    let mut err = if error {
        ecx.tcx.sess.struct_span_err(span, title)
    } else {
        ecx.tcx.sess.diagnostic().span_note_diag(span, title)
    };
    err.span_label(span, span_msg);
    if !helps.is_empty() {
        // Add visual separator before backtrace.
        helps.last_mut().unwrap().push_str("\n");
        for help in helps {
            err.help(&help);
        }
    }
    // Add backtrace
    let frames = ecx.generate_stacktrace();
    for (idx, frame_info) in frames.iter().enumerate() {
        let is_local = frame_info.instance.def_id().is_local();
        // No span for non-local frames and the first frame (which is the error site).
        if is_local && idx > 0 {
            err.span_note(frame_info.span, &frame_info.to_string());
        } else {
            err.note(&frame_info.to_string());
        }
    }

    err.emit();

    for (i, frame) in ecx.machine.stack.iter().enumerate() {
        trace!("-------------------");
        trace!("Frame {}", i);
        trace!("    return: {:?}", frame.return_place.map(|p| *p));
        for (i, local) in frame.locals.iter().enumerate() {
            trace!("    local {}: {:?}", i, local.value);
        }
    }
    // Let the reported error determine the return code.
    return None;
}

thread_local! {
    static DIAGNOSTICS: RefCell<Vec<NonHaltingDiagnostic>> = RefCell::new(Vec::new());
}

/// Schedule a diagnostic for emitting. This function works even if you have no `InterpCx` available.
/// The diagnostic will be emitted after the current interpreter step is finished.
pub fn register_diagnostic(e: NonHaltingDiagnostic) {
    DIAGNOSTICS.with(|diagnostics| diagnostics.borrow_mut().push(e));
}

impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    /// Emit all diagnostics that were registed with `register_diagnostics`
    fn process_diagnostics(&self) {
        let this = self.eval_context_ref();
        DIAGNOSTICS.with(|diagnostics| {
            for e in diagnostics.borrow_mut().drain(..) {
                use NonHaltingDiagnostic::*;
                let msg = match e {
                    PoppedTrackedPointerTag(item) =>
                        format!("popped tracked tag for item {:?}", item),
                    CreatedAlloc(AllocId(id)) =>
                        format!("created allocation with id {}", id),
                    FreedAlloc(AllocId(id)) =>
                        format!("freed allocation with id {}", id),
                };
                report_msg(this, "tracking was triggered", msg, vec![], false);
            }
        });
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::f64;

use itertools::Itertools;
use ndarray::prelude::*;
use bit_vec::BitVec;
use ordered_float::NotNaN;
use ndarray_rand::RandomExt;
use rand::distributions::Range;

use bio::stats::{Prob, LogProb};

use io::codebook::Codebook;

pub type Readout = BitVec;

/// Estimate position-wise error rates as presented by Chen et al. 2015.
pub fn estimate<I: Iterator<Item=(String, Readout)>>(
    codebook: &Codebook,
    readouts: I
) -> (Vec<Prob>, Vec<Prob>) {
    let max_diff = 0.001;
    let shape = (codebook.len(), codebook.N as usize);

    let mut observed_01_errors = Array2::from_elem(shape, 0.0);
    let mut observed_10_errors = Array2::from_elem(shape, 0.0);
    let mut exact_count = Array2::from_elem((codebook.len(), 1), 0.0);

    for (feat, readout) in readouts {
        let feature_id = codebook.get_id(&feat);
        let rec = codebook.record(feature_id);
        if !rec.expressed() {
            continue;
        }
        let encoding = rec.codeword();

        let mut err_count = 0;
        for k in 0..codebook.N as usize {
            match (encoding[k], readout[k]) {
                (true, true) | (false, false) => exact_count[(feature_id, 0)] += 1.0,
                (false, true) => {
                    observed_01_errors[(feature_id, k)] += 1.0;
                    err_count += 1;
                },
                (true, false) => {
                    observed_10_errors[(feature_id, k)] += 1.0;
                    err_count += 1;
                }
            };
        }
        assert!(
            err_count <= 1,
            "unexpected number of errors in readout: {} (<=1 expected)",
            err_count
        );
    }

    debug!("10: {:?}", observed_10_errors);

    // calculate observed (joint) error rates
    let observed_p0 = observed_01_errors / &exact_count;
    let observed_p1 = observed_10_errors / &exact_count;

    // estimate error rates
    let feat_p0 = observed_p0.map(|&o| o / (1.0 + o));
    let feat_p1 = observed_p1.map(|&o| o / (1.0 + o));

    //debug!("p0 {:?}", feat_p0);
    debug!("p1 {:?}", feat_p1);

    let mut p0 = Vec::new();
    let mut p1 = Vec::new();
    for k in 0..codebook.N as usize {
        let p = |feat_p: &Array2<f64>, bit: bool| {
            let mut count = 0.0;
            let p = (0..codebook.len()).filter_map(|feature_id| {
                let encoding = codebook.record(feature_id).codeword();
                if exact_count[(feature_id, 0)] < 10.0 || encoding[k] != bit {
                    None
                } else {
                    count += 1.0;
                    Some(feat_p[(feature_id, k)])
                }
            }).sum::<f64>() / count;
            if count == 0.0 {
                panic!("not enough counts to estimate error rate (at least 1 feature with 50 counts over all cells required)");
            }
            p
        };

        p0.push(Prob(p(&feat_p0, false)));
        p1.push(Prob(p(&feat_p1, true)));
    }

    (p0, p1)
}

// pub fn estimate<I: Iterator<Item=(String, Readout)>>(
//     codebook: &Codebook,
//     readouts: I
// ) -> (Vec<Prob>, Vec<Prob>) {
//     let max_diff = 0.001;
//     let shape = (codebook.len(), codebook.N as usize);
//
//     let mut observed_01_errors = Array2::from_elem(shape, 0.0);
//     let mut observed_10_errors = Array2::from_elem(shape, 0.0);
//     let mut feat_count = Array2::from_elem((codebook.len(), 1), 0.0);
//
//     for (feat, readout) in readouts {
//         let feature_id = codebook.get_id(&feat);
//         let rec = codebook.record(feature_id);
//         if !rec.expressed() {
//             continue;
//         }
//         let encoding = rec.codeword();
//
//         // count features
//         feat_count[(feature_id, 0)] += 1.0;
//
//         let mut err_count = 0;
//         for k in 0..codebook.N as usize {
//             if encoding[k] == false {
//                 // count 01 errors
//                 if readout[k] == true {
//                     observed_01_errors[(feature_id, k)] += 1.0;
//                     err_count += 1;
//                 }
//             } else {
//                 // count 10 errors
//                 if readout[k] == false {
//                     observed_10_errors[(feature_id, k)] += 1.0;
//                     err_count += 1;
//                 }
//             }
//         }
//         assert!(
//             err_count <= 1,
//             "unexpected number of errors in readout: {} (<=1 expected)",
//             err_count
//         );
//     }
//
//     // calculate observed (joint) error rates
//     let observed_p0 = observed_01_errors / &feat_count;
//     let observed_p1 = observed_10_errors / &feat_count;
//     debug!("p0 {:?}", observed_p0);
//     debug!("p1 {:?}", observed_p1);
//
//     // run EM algorithm to estimate error rates
//     let mut prob_no_error = Array2::from_elem(
//         (codebook.len(), codebook.N as usize), LogProb::ln_one()
//     );
//
//
//     let mut p0 = Array1::random(codebook.N as usize, Range::new(0.0, 1.0));
//     let mut p1 = Array1::random(codebook.N as usize, Range::new(0.0, 1.0));
//
//     let mut p0_last = Array1::from_elem(codebook.N as usize, 0.0);
//     let mut p1_last = Array1::from_elem(codebook.N as usize, 0.0);
//     for i in 0..1000 {
//         // E-step: estimate probability to have no errors in rest of readout
//         for feature_id in 0..codebook.len() {
//             let encoding = codebook.record(feature_id).codeword();
//             for k in 0..codebook.N as usize {
//                 let p = LogProb((0..codebook.N as usize).filter_map(|l| {
//                     if l != k {
//                         let p_err = if encoding[l] == false {
//                             p0[k]
//                         } else {
//                             p1[k]
//                         };
//                         Some(*LogProb((p_err as f64).ln()).ln_one_minus_exp())
//                     } else { None }
//                 }).sum());
//                 prob_no_error[(feature_id, k)] = p;
//             }
//         }
//
//         // M-step: find p0 and p1 that maximizes the likelihood
//         mem::swap(&mut p0, &mut p0_last);
//         mem::swap(&mut p1, &mut p1_last);
//         for k in 0..codebook.N as usize {
//             // solve least squares: take mean of all estimates
//             let p = |observed_p: &Array2<f64>, bit: bool| {
//                 let mut count = 0.0;
//                 let p = (0..codebook.len()).filter_map(|feature_id| {
//                     let encoding = codebook.record(feature_id).codeword();
//                     if feat_count[(feature_id, 0)] < 100.0 || encoding[k] != bit {
//                         None
//                     } else {
//                         count += 1.0;
//                         let p = observed_p[(feature_id, k)] * prob_no_error[(feature_id, k)].exp();
//                         if k == 4 {
//                             debug!("p={}, c={}, obs={}, noerr={}", p, feat_count[(feature_id, 0)], observed_p[(feature_id, k)], prob_no_error[(feature_id, k)].exp());
//                         }
//                         Some(p)
//                     }
//                 }).sum::<f64>() / count;
//                 if count == 0.0 {
//                     panic!("not enough counts to estimate error rate (at least 1 feature with 50 counts over all cells required)");
//                 }
//                 p
//             };
//             debug!("----------- p0 ------------");
//             p0[k] = p(&observed_p0, false);
//             //debug!("DEBUG: p0={}", p0[k]);
//             debug!("----------- p1 ------------");
//             p1[k] = p(&observed_p1, true);
//             //debug!("DEBUG: p1={}", p1[k]);
//         }
//
//         // check convergence
//         let abs = |d: &f64| NotNaN::new(d.abs()).unwrap();
//         //debug!("{:?}", p0);
//         let convergence = p0.all_close(&p0_last, max_diff) && p1.all_close(&p1_last, max_diff);
//
//         if convergence && i >= 5 {
//             debug!("convergence reached");
//             debug!("{:?}", p1);
//             break;
//         }
//
//         debug!("EM-algorithm step {} of {}.", i + 1, 100);
//     }
//
//     (
//         p0.iter().map(|p| Prob(*p)).collect_vec(),
//         p1.iter().map(|p| Prob(*p)).collect_vec()
//     )
// }
<commit_msg>Fixes.<commit_after>use std::mem;
use std::f64;

use itertools::Itertools;
use ndarray::prelude::*;
use bit_vec::BitVec;
use ordered_float::NotNaN;
use ndarray_rand::RandomExt;
use rand::distributions::Range;

use bio::stats::{Prob, LogProb};

use io::codebook::Codebook;

pub type Readout = BitVec;

/// Estimate position-wise error rates as presented by Chen et al. 2015.
pub fn estimate<I: Iterator<Item=(String, Readout)>>(
    codebook: &Codebook,
    readouts: I
) -> (Vec<Prob>, Vec<Prob>) {
    let max_diff = 0.001;
    let shape = (codebook.len(), codebook.N as usize);

    let mut observed_01_errors = Array2::from_elem(shape, 0.0);
    let mut observed_10_errors = Array2::from_elem(shape, 0.0);
    let mut exact_count = Array2::from_elem((codebook.len(), 1), 0.0);

    for (feat, readout) in readouts {
        let feature_id = codebook.get_id(&feat);
        let rec = codebook.record(feature_id);
        if !rec.expressed() {
            continue;
        }
        let encoding = rec.codeword();

        let mut err_count = 0;
        for k in 0..codebook.N as usize {
            match (encoding[k], readout[k]) {
                (false, true) => {
                    observed_01_errors[(feature_id, k)] += 1.0;
                    err_count += 1;
                },
                (true, false) => {
                    observed_10_errors[(feature_id, k)] += 1.0;
                    err_count += 1;
                },
                _ => ()
            };
        }
        assert!(
            err_count <= 1,
            "unexpected number of errors in readout: {} (<=1 expected)",
            err_count
        );
        if err_count == 0 {
            exact_count[(feature_id, 0)] += 1.0;
        }
    }

    debug!("10: {:?}", observed_10_errors);

    // calculate observed (joint) error rates
    let observed_p0 = observed_01_errors / &exact_count;
    let observed_p1 = observed_10_errors / &exact_count;

    // estimate error rates
    let feat_p0 = observed_p0.map(|&o| o / (1.0 + o));
    let feat_p1 = observed_p1.map(|&o| o / (1.0 + o));

    //debug!("p0 {:?}", feat_p0);
    debug!("p1 {:?}", feat_p1);

    let mut p0 = Vec::new();
    let mut p1 = Vec::new();
    for k in 0..codebook.N as usize {
        let p = |feat_p: &Array2<f64>, bit: bool| {
            let mut count = 0.0;
            let p = (0..codebook.len()).filter_map(|feature_id| {
                let encoding = codebook.record(feature_id).codeword();
                if exact_count[(feature_id, 0)] < 100.0 || encoding[k] != bit {
                    None
                } else {
                    count += 1.0;
                    Some(feat_p[(feature_id, k)])
                }
            }).sum::<f64>() / count;
            if count == 0.0 {
                panic!("not enough counts to estimate error rate (at least 1 feature with 50 counts over all cells required)");
            }
            p
        };

        p0.push(Prob(p(&feat_p0, false)));
        p1.push(Prob(p(&feat_p1, true)));
    }

    (p0, p1)
}
<|endoftext|>


<commit_before>use renderer::html_handlebars::helpers;
use renderer::Renderer;
use book::MDBook;
use book::bookitem::BookItem;
use {utils, theme};
use regex::{Regex, Captures};

use std::ascii::AsciiExt;
use std::path::{Path, PathBuf};
use std::fs::{self, File};
use std::error::Error;
use std::io::{self, Read};
use std::collections::BTreeMap;

use handlebars::Handlebars;

use serde_json;

#[derive(Default)]
pub struct HtmlHandlebars;

impl HtmlHandlebars {
    pub fn new() -> Self {
        HtmlHandlebars
    }
}

impl Renderer for HtmlHandlebars {
    fn render(&self, book: &MDBook) -> Result<(), Box<Error>> {
        debug!("[fn]: render");
        let mut handlebars = Handlebars::new();

        // Load theme
        let theme = theme::Theme::new(book.get_theme_path());

        // Register template
        debug!("[*]: Register handlebars template");
        try!(handlebars.register_template_string("index", try!(String::from_utf8(theme.index))));

        // Register helpers
        debug!("[*]: Register handlebars helpers");
        handlebars.register_helper("toc", Box::new(helpers::toc::RenderToc));
        handlebars.register_helper("previous", Box::new(helpers::navigation::previous));
        handlebars.register_helper("next", Box::new(helpers::navigation::next));

        let mut data = try!(make_data(book));

        // Print version
        let mut print_content: String = String::new();

        // Check if dest directory exists
        debug!("[*]: Check if destination directory exists");
        if fs::create_dir_all(book.get_dest()).is_err() {
            return Err(Box::new(io::Error::new(io::ErrorKind::Other,
                                               "Unexpected error when constructing destination path")));
        }

        // Render a file for every entry in the book
        let mut index = true;
        for item in book.iter() {

            match *item {
                BookItem::Chapter(_, ref ch) |
                BookItem::Affix(ref ch) => {
                    if ch.path != PathBuf::new() {

                        let path = book.get_src().join(&ch.path);

                        debug!("[*]: Opening file: {:?}", path);
                        let mut f = try!(File::open(&path));
                        let mut content: String = String::new();

                        debug!("[*]: Reading file");
                        try!(f.read_to_string(&mut content));

                        // Parse for playpen links
                        if let Some(p) = path.parent() {
                            content = helpers::playpen::render_playpen(&content, p);
                        }

                        // Render markdown using the pulldown-cmark crate
                        content = utils::render_markdown(&content);
                        print_content.push_str(&content);

                        // Update the context with data for this file
                        let path = ch.path.to_str().ok_or_else(||
                            io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?;
                        data.insert("path".to_owned(), json!(path));
                        data.insert("content".to_owned(), json!(content));
                        data.insert("chapter_title".to_owned(), json!(ch.name));
                        data.insert("path_to_root".to_owned(), json!(utils::fs::path_to_root(&ch.path)));

                        // Render the handlebars template with the data
                        debug!("[*]: Render template");
                        let rendered = try!(handlebars.render("index", &data));

                        // create links for headers
                        let rendered = build_header_links(rendered);

                        // fix code blocks
                        let rendered = fix_code_blocks(rendered);

                        // Write to file
                        let filename = Path::new(&ch.path).with_extension("html");
                        info!("[*] Creating {:?} ✓", filename.display());
                        try!(book.write_file(filename, &rendered.into_bytes()));

                        // Create an index.html from the first element in SUMMARY.md
                        if index {
                            debug!("[*]: index.html");

                            let mut content = String::new();
                            let _source = try!(File::open(book.get_dest().join(&ch.path.with_extension("html"))))
                                .read_to_string(&mut content);

                            // This could cause a problem when someone displays code containing <base href=...>
                            // on the front page, however this case should be very very rare...
                            content = content.lines()
                                .filter(|line| !line.contains("<base href="))
                                .collect::<Vec<&str>>()
                                .join("\n");

                            try!(book.write_file("index.html", content.as_bytes()));

                            info!("[*] Creating index.html from {:?} ✓",
                                  book.get_dest().join(&ch.path.with_extension("html")));
                            index = false;
                        }
                    }
                },
                _ => {},
            }
        }

        // Print version

        // Update the context with data for this file
        data.insert("path".to_owned(), json!("print.md"));
        data.insert("content".to_owned(), json!(print_content));
        data.insert("path_to_root".to_owned(), json!(utils::fs::path_to_root(Path::new("print.md"))));

        // Render the handlebars template with the data
        debug!("[*]: Render template");

        let rendered = try!(handlebars.render("index", &data));
        let rendered = build_header_links(rendered);

        // fix code blocks
        let rendered = fix_code_blocks(rendered);

        try!(book.write_file(Path::new("print").with_extension("html"), &rendered.into_bytes()));
        info!("[*] Creating print.html ✓");

        // Copy static files (js, css, images, ...)

        debug!("[*] Copy static files");
        try!(book.write_file("book.js", &theme.js));
        try!(book.write_file("book.css", &theme.css));
        try!(book.write_file("favicon.png", &theme.favicon));
        try!(book.write_file("jquery.js", &theme.jquery));
        try!(book.write_file("highlight.css", &theme.highlight_css));
        try!(book.write_file("tomorrow-night.css", &theme.tomorrow_night_css));
        try!(book.write_file("highlight.js", &theme.highlight_js));
        try!(book.write_file("_FontAwesome/css/font-awesome.css", theme::FONT_AWESOME));
        try!(book.write_file("_FontAwesome/fonts/fontawesome-webfont.eot", theme::FONT_AWESOME_EOT));
        try!(book.write_file("_FontAwesome/fonts/fontawesome-webfont.svg", theme::FONT_AWESOME_SVG));
        try!(book.write_file("_FontAwesome/fonts/fontawesome-webfont.ttf", theme::FONT_AWESOME_TTF));
        try!(book.write_file("_FontAwesome/fonts/fontawesome-webfont.woff", theme::FONT_AWESOME_WOFF));
        try!(book.write_file("_FontAwesome/fonts/fontawesome-webfont.woff2", theme::FONT_AWESOME_WOFF2));
        try!(book.write_file("_FontAwesome/fonts/FontAwesome.ttf", theme::FONT_AWESOME_TTF));

        // Copy all remaining files
        try!(utils::fs::copy_files_except_ext(book.get_src(), book.get_dest(), true, &["md"]));

        Ok(())
    }
}

fn make_data(book: &MDBook) -> Result<serde_json::Map<String, serde_json::Value>, Box<Error>> {
    debug!("[fn]: make_data");

    let mut data = serde_json::Map::new();
    data.insert("language".to_owned(), json!("en"));
    data.insert("title".to_owned(), json!(book.get_title()));
    data.insert("description".to_owned(), json!(book.get_description()));
    data.insert("favicon".to_owned(), json!("favicon.png"));
    if let Some(livereload) = book.get_livereload() {
        data.insert("livereload".to_owned(), json!(livereload));
    }

    let mut chapters = vec![];

    for item in book.iter() {
        // Create the data to inject in the template
        let mut chapter = BTreeMap::new();

        match *item {
            BookItem::Affix(ref ch) => {
                chapter.insert("name".to_owned(), json!(ch.name));
                let path = ch.path.to_str().ok_or_else(||
                    io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?;
                chapter.insert("path".to_owned(), json!(path));
            },
            BookItem::Chapter(ref s, ref ch) => {
                chapter.insert("section".to_owned(), json!(s));
                chapter.insert("name".to_owned(), json!(ch.name));
                let path = ch.path.to_str().ok_or_else(||
                    io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?;
                chapter.insert("path".to_owned(), json!(path));
            },
            BookItem::Spacer => {
                chapter.insert("spacer".to_owned(), json!("_spacer_"));
            },

        }

        chapters.push(chapter);
    }

    data.insert("chapters".to_owned(), json!(chapters));

    debug!("[*]: JSON constructed");
    Ok(data)
}

fn build_header_links(html: String) -> String {
    let regex = Regex::new(r"<h(\d)>(.*?)</h\d>").unwrap();

    regex.replace_all(&html, |caps: &Captures| {
        let level = &caps[1];
        let text = &caps[2];
        let mut id = text.to_string();
        let repl_sub = vec!["", "", "", "",
                            "", "",
                            "<", ">", "&", "'", """];
        for sub in repl_sub {
            id = id.replace(sub, "");
        }
        let id = id.chars().filter_map(|c| {
            if c.is_alphanumeric() || c == '-' || c == '_' {
                if c.is_ascii() {
                    Some(c.to_ascii_lowercase())
                } else {
                    Some(c)
                }
            } else if c.is_whitespace() && c.is_ascii() {
                Some('-')
            } else {
                None
            }
        }).collect::<String>();

        format!("<h{level}>{text}</h{level}>", level=level, id=id, text=text)
    }).into_owned()
}

// The rust book uses annotations for rustdoc to test code snippets, like the following:
// ```rust,should_panic
// fn main() {
//     // Code here
// }
// ```
// This function replaces all commas by spaces in the code block classes
fn fix_code_blocks(html: String) -> String {
    let regex = Regex::new(r##"]+)class="([^"]+)"([^>]*)>"##).unwrap();
    regex.replace_all(&html, |caps: &Captures| {
        let before = &caps[1];
        let classes = &caps[2].replace(",", " ");
        let after = &caps[3];

        format!("", before=before, classes=classes, after=after)
    }).into_owned()
}
<commit_msg>Fix anchors, Fixes #211<commit_after>use renderer::html_handlebars::helpers;
use renderer::Renderer;
use book::MDBook;
use book::bookitem::BookItem;
use {utils, theme};
use regex::{Regex, Captures};

use std::ascii::AsciiExt;
use std::path::{Path, PathBuf};
use std::fs::{self, File};
use std::error::Error;
use std::io::{self, Read};
use std::collections::BTreeMap;

use handlebars::Handlebars;

use serde_json;

#[derive(Default)]
pub struct HtmlHandlebars;

impl HtmlHandlebars {
    pub fn new() -> Self {
        HtmlHandlebars
    }
}

impl Renderer for HtmlHandlebars {
    fn render(&self, book: &MDBook) -> Result<(), Box<Error>> {
        debug!("[fn]: render");
        let mut handlebars = Handlebars::new();

        // Load theme
        let theme = theme::Theme::new(book.get_theme_path());

        // Register template
        debug!("[*]: Register handlebars template");
        try!(handlebars.register_template_string("index", try!(String::from_utf8(theme.index))));

        // Register helpers
        debug!("[*]: Register handlebars helpers");
        handlebars.register_helper("toc", Box::new(helpers::toc::RenderToc));
        handlebars.register_helper("previous", Box::new(helpers::navigation::previous));
        handlebars.register_helper("next", Box::new(helpers::navigation::next));

        let mut data = try!(make_data(book));

        // Print version
        let mut print_content: String = String::new();

        // Check if dest directory exists
        debug!("[*]: Check if destination directory exists");
        if fs::create_dir_all(book.get_dest()).is_err() {
            return Err(Box::new(io::Error::new(io::ErrorKind::Other,
                                               "Unexpected error when constructing destination path")));
        }

        // Render a file for every entry in the book
        let mut index = true;
        for item in book.iter() {

            match *item {
                BookItem::Chapter(_, ref ch) |
                BookItem::Affix(ref ch) => {
                    if ch.path != PathBuf::new() {

                        let path = book.get_src().join(&ch.path);

                        debug!("[*]: Opening file: {:?}", path);
                        let mut f = try!(File::open(&path));
                        let mut content: String = String::new();

                        debug!("[*]: Reading file");
                        try!(f.read_to_string(&mut content));

                        // Parse for playpen links
                        if let Some(p) = path.parent() {
                            content = helpers::playpen::render_playpen(&content, p);
                        }

                        // Render markdown using the pulldown-cmark crate
                        content = utils::render_markdown(&content);
                        print_content.push_str(&content);

                        // Update the context with data for this file
                        let path = ch.path.to_str().ok_or_else(||
                            io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?;
                        data.insert("path".to_owned(), json!(path));
                        data.insert("content".to_owned(), json!(content));
                        data.insert("chapter_title".to_owned(), json!(ch.name));
                        data.insert("path_to_root".to_owned(), json!(utils::fs::path_to_root(&ch.path)));

                        // Render the handlebars template with the data
                        debug!("[*]: Render template");
                        let rendered = try!(handlebars.render("index", &data));

                        let filename = Path::new(&ch.path).with_extension("html");

                        // create links for headers
                        let rendered = build_header_links(rendered, filename.to_str().unwrap_or(""));

                        // fix code blocks
                        let rendered = fix_code_blocks(rendered);

                        // Write to file
                        info!("[*] Creating {:?} ✓", filename.display());
                        try!(book.write_file(filename, &rendered.into_bytes()));

                        // Create an index.html from the first element in SUMMARY.md
                        if index {
                            debug!("[*]: index.html");

                            let mut content = String::new();
                            let _source = try!(File::open(book.get_dest().join(&ch.path.with_extension("html"))))
                                .read_to_string(&mut content);

                            // This could cause a problem when someone displays code containing <base href=...>
                            // on the front page, however this case should be very very rare...
                            content = content.lines()
                                .filter(|line| !line.contains("<base href="))
                                .collect::<Vec<&str>>()
                                .join("\n");

                            try!(book.write_file("index.html", content.as_bytes()));

                            info!("[*] Creating index.html from {:?} ✓",
                                  book.get_dest().join(&ch.path.with_extension("html")));
                            index = false;
                        }
                    }
                },
                _ => {},
            }
        }

        // Print version

        // Update the context with data for this file
        data.insert("path".to_owned(), json!("print.md"));
        data.insert("content".to_owned(), json!(print_content));
        data.insert("path_to_root".to_owned(), json!(utils::fs::path_to_root(Path::new("print.md"))));

        // Render the handlebars template with the data
        debug!("[*]: Render template");

        let rendered = try!(handlebars.render("index", &data));
        let rendered = build_header_links(rendered, "print.html");

        // fix code blocks
        let rendered = fix_code_blocks(rendered);

        try!(book.write_file(Path::new("print").with_extension("html"), &rendered.into_bytes()));
        info!("[*] Creating print.html ✓");

        // Copy static files (js, css, images, ...)

        debug!("[*] Copy static files");
        try!(book.write_file("book.js", &theme.js));
        try!(book.write_file("book.css", &theme.css));
        try!(book.write_file("favicon.png", &theme.favicon));
        try!(book.write_file("jquery.js", &theme.jquery));
        try!(book.write_file("highlight.css", &theme.highlight_css));
        try!(book.write_file("tomorrow-night.css", &theme.tomorrow_night_css));
        try!(book.write_file("highlight.js", &theme.highlight_js));
        try!(book.write_file("_FontAwesome/css/font-awesome.css", theme::FONT_AWESOME));
        try!(book.write_file("_FontAwesome/fonts/fontawesome-webfont.eot", theme::FONT_AWESOME_EOT));
        try!(book.write_file("_FontAwesome/fonts/fontawesome-webfont.svg", theme::FONT_AWESOME_SVG));
        try!(book.write_file("_FontAwesome/fonts/fontawesome-webfont.ttf", theme::FONT_AWESOME_TTF));
        try!(book.write_file("_FontAwesome/fonts/fontawesome-webfont.woff", theme::FONT_AWESOME_WOFF));
        try!(book.write_file("_FontAwesome/fonts/fontawesome-webfont.woff2", theme::FONT_AWESOME_WOFF2));
        try!(book.write_file("_FontAwesome/fonts/FontAwesome.ttf", theme::FONT_AWESOME_TTF));

        // Copy all remaining files
        try!(utils::fs::copy_files_except_ext(book.get_src(), book.get_dest(), true, &["md"]));

        Ok(())
    }
}

fn make_data(book: &MDBook) -> Result<serde_json::Map<String, serde_json::Value>, Box<Error>> {
    debug!("[fn]: make_data");

    let mut data = serde_json::Map::new();
    data.insert("language".to_owned(), json!("en"));
    data.insert("title".to_owned(), json!(book.get_title()));
    data.insert("description".to_owned(), json!(book.get_description()));
    data.insert("favicon".to_owned(), json!("favicon.png"));
    if let Some(livereload) = book.get_livereload() {
        data.insert("livereload".to_owned(), json!(livereload));
    }

    let mut chapters = vec![];

    for item in book.iter() {
        // Create the data to inject in the template
        let mut chapter = BTreeMap::new();

        match *item {
            BookItem::Affix(ref ch) => {
                chapter.insert("name".to_owned(), json!(ch.name));
                let path = ch.path.to_str().ok_or_else(||
                    io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?;
                chapter.insert("path".to_owned(), json!(path));
            },
            BookItem::Chapter(ref s, ref ch) => {
                chapter.insert("section".to_owned(), json!(s));
                chapter.insert("name".to_owned(), json!(ch.name));
                let path = ch.path.to_str().ok_or_else(||
                    io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?;
                chapter.insert("path".to_owned(), json!(path));
            },
            BookItem::Spacer => {
                chapter.insert("spacer".to_owned(), json!("_spacer_"));
            },

        }

        chapters.push(chapter);
    }

    data.insert("chapters".to_owned(), json!(chapters));

    debug!("[*]: JSON constructed");
    Ok(data)
}

fn build_header_links(html: String, filename: &str) -> String {
    let regex = Regex::new(r"<h(\d)>(.*?)</h\d>").unwrap();

    regex.replace_all(&html, |caps: &Captures| {
        let level = &caps[1];
        let text = &caps[2];
        let mut id = text.to_string();
        let repl_sub = vec!["", "", "", "",
                            "", "",
                            "<", ">", "&", "'", """];
        for sub in repl_sub {
            id = id.replace(sub, "");
        }
        let id = id.chars().filter_map(|c| {
            if c.is_alphanumeric() || c == '-' || c == '_' {
                if c.is_ascii() {
                    Some(c.to_ascii_lowercase())
                } else {
                    Some(c)
                }
            } else if c.is_whitespace() && c.is_ascii() {
                Some('-')
            } else {
                None
            }
        }).collect::<String>();

        format!("<h{level}>{text}</h{level}>",
            level=level, id=id, text=text, filename=filename)
    }).into_owned()
}

// The rust book uses annotations for rustdoc to test code snippets, like the following:
// ```rust,should_panic
// fn main() {
//     // Code here
// }
// ```
// This function replaces all commas by spaces in the code block classes
fn fix_code_blocks(html: String) -> String {
    let regex = Regex::new(r##"]+)class="([^"]+)"([^>]*)>"##).unwrap();
    regex.replace_all(&html, |caps: &Captures| {
        let before = &caps[1];
        let classes = &caps[2].replace(",", " ");
        let after = &caps[3];

        format!("", before=before, classes=classes, after=after)
    }).into_owned()
}
<|endoftext|>


<commit_before>/*!
helper functions used by this crate
whose utility surpasses the confines of this crate.

generic things that are also useful in other crates.
*/

mod repeatedly;
pub use self::repeatedly::{Repeatedly, repeatedly};

// this needs to be public otherwise the impl is not exported
pub mod normalize;
pub use self::normalize::Normalize;

mod partial_max;
pub use self::partial_max::PartialMaxIteratorExt;

mod random;
pub use self::random::random01;

pub mod to_image;
pub use self::to_image::ToImage;

mod magnify;
pub use self::magnify::magnify;
<commit_msg>add type aliases to helpers to clean up code<commit_after>/*!
helper functions used by this crate
whose utility surpasses the confines of this crate.

generic things that are also useful in other crates.
*/

use ndarray::ArrayBase;

pub type Dims = (usize, usize);
pub type Array2D<T> = ArrayBase<Vec<T>, Dims>;

mod repeatedly;
pub use self::repeatedly::{Repeatedly, repeatedly};

// this needs to be public otherwise the impl is not exported
pub mod normalize;
pub use self::normalize::Normalize;

mod partial_max;
pub use self::partial_max::PartialMaxIteratorExt;

mod random;
pub use self::random::random01;

pub mod to_image;
pub use self::to_image::ToImage;

mod magnify;
pub use self::magnify::magnify;
<|endoftext|>


<commit_before>// ignore-tidy-linelength
// ignore-windows failing on win32 bot
// ignore-freebsd: gdb package too new
// ignore-android: FIXME(#10381)
// compile-flags:-g

// The pretty printers being tested here require the patch from
// https://sourceware.org/bugzilla/show_bug.cgi?id=21763
// min-gdb-version: 8.1

// min-lldb-version: 310

// === GDB TESTS ===================================================================================

// gdb-command: run

// gdb-command: print btree_set
// gdb-check:$1 = BTreeSet(size=15) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}

// gdb-command: print empty_btree_set
// gdb-check:$2 = BTreeSet(size=0)

// gdb-command: print btree_map
// gdb-check:$3 = BTreeMap(size=15) = {[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7, [8] = 8, [9] = 9, [10] = 10, [11] = 11, [12] = 12, [13] = 13, [14] = 14}

// gdb-command: print empty_btree_map
// gdb-check:$4 = BTreeMap(size=0)

// gdb-command: print option_btree_map
// gdb-check:$5 = BTreeMap(size=2) = {[false] = [...], [true] = [...]}
// (abbreviated because both values vary wildly over gdb versions and/or linux distributions)

// gdb-command: print nasty_btree_map
// gdb-check:$6 = BTreeMap(size=15) = {[0] = pretty_std_collections::MyLeafNode (0), [...]}
// (abbreviated because it's boring but we need enough elements to include internal nodes)

// gdb-command: print zst_key_btree_map
// gdb-check:$7 = BTreeMap(size=1) = {[()] = 1}

// gdb-command: print zst_val_btree_map
// gdb-check:$8 = BTreeMap(size=1) = {[1] = ()}

// gdb-command: print zst_key_val_btree_map
// gdb-check:$9 = BTreeMap(size=1) = {[()] = ()}

// gdb-command: print vec_deque
// gdb-check:$10 = VecDeque(size=3) = {5, 3, 7}

// gdb-command: print vec_deque2
// gdb-check:$11 = VecDeque(size=7) = {2, 3, 4, 5, 6, 7, 8}

// gdb-command: print hash_map
// gdb-check:$12 = HashMap(size=4) = {[1] = 10, [2] = 20, [3] = 30, [4] = 40}

// gdb-command: print hash_set
// gdb-check:$13 = HashSet(size=4) = {1, 2, 3, 4}

// === LLDB TESTS ==================================================================================

// lldb-command:run

// lldb-command:print vec_deque
// lldbg-check:[...]$0 = size=3 { [0] = 5 [1] = 3 [2] = 7 }
// lldbr-check:(alloc::collections::vec_deque::VecDeque<i32>) vec_deque = size=3 = { [0] = 5 [1] = 3 [2] = 7 }

// lldb-command:print vec_deque2
// lldbg-check:[...]$1 = size=7 { [0] = 2 [1] = 3 [2] = 4 [3] = 5 [4] = 6 [5] = 7 [6] = 8 }
// lldbr-check:(alloc::collections::vec_deque::VecDeque<i32>) vec_deque2 = size=7 = { [0] = 2 [1] = 3 [2] = 4 [3] = 5 [4] = 6 [5] = 7 [6] = 8 }

// lldb-command:print hash_map
// lldbg-check:[...]$2 = size=4 { [0] = { 0 = 1 1 = 10 } [1] = { 0 = 2 1 = 20 } [2] = { 0 = 3 1 = 30 } [3] = { 0 = 4 1 = 40 } }
// lldbr-check:(std::collections::hash::map::HashMap<u64, u64, [...]>) hash_map = size=4 size=4 { [0] = { 0 = 1 1 = 10 } [1] = { 0 = 2 1 = 20 } [2] = { 0 = 3 1 = 30 } [3] = { 0 = 4 1 = 40 } }

// lldb-command:print hash_set
// lldbg-check:[...]$3 = size=4 { [0] = 1 [1] = 2 [2] = 3 [3] = 4 }
// lldbr-check:(std::collections::hash::set::HashSet<u64, [...]>) hash_set = size=4 { [0] = 1 [1] = 2 [2] = 3 [3] = 4 }

#![allow(unused_variables)]
use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::collections::HashMap;
use std::collections::HashSet;
use std::collections::VecDeque;
use std::hash::{BuildHasherDefault, Hasher};

struct MyLeafNode(i32); // helps to ensure we don't blindly replace substring "LeafNode"

#[derive(Default)]
struct SimpleHasher { hash: u64 }

impl Hasher for SimpleHasher {
    fn finish(&self) -> u64 { self.hash }
    fn write(&mut self, bytes: &[u8]) {}
    fn write_u64(&mut self, i: u64) { self.hash = i }
}

fn main() {
    // BTreeSet
    let mut btree_set = BTreeSet::new();
    for i in 0..15 {
        btree_set.insert(i);
    }

    let mut empty_btree_set: BTreeSet<i32> = BTreeSet::new();

    // BTreeMap
    let mut btree_map = BTreeMap::new();
    for i in 0..15 {
        btree_map.insert(i, i);
    }

    let mut empty_btree_map: BTreeMap<i32, u32> = BTreeMap::new();

    let mut option_btree_map: BTreeMap<bool, Option<bool>> = BTreeMap::new();
    option_btree_map.insert(false, None);
    option_btree_map.insert(true, Some(true));

    let mut nasty_btree_map: BTreeMap<i32, MyLeafNode> = BTreeMap::new();
    for i in 0..15 {
        nasty_btree_map.insert(i, MyLeafNode(i));
    }

    let mut zst_key_btree_map: BTreeMap<(), i32> = BTreeMap::new();
    zst_key_btree_map.insert((), 1);

    let mut zst_val_btree_map: BTreeMap<i32, ()> = BTreeMap::new();
    zst_val_btree_map.insert(1, ());

    let mut zst_key_val_btree_map: BTreeMap<(), ()> = BTreeMap::new();
    zst_key_val_btree_map.insert((), ());

    // VecDeque
    let mut vec_deque = VecDeque::new();
    vec_deque.push_back(5);
    vec_deque.push_back(3);
    vec_deque.push_back(7);

    // VecDeque where an element was popped.
    let mut vec_deque2 = VecDeque::new();
    for i in 1..8 {
        vec_deque2.push_back(i)
    }
    vec_deque2.pop_front();
    vec_deque2.push_back(8);

    // HashMap
    let mut hash_map = HashMap::<u64, u64, BuildHasherDefault<SimpleHasher>>::default();
    for i in 1..5 {
        hash_map.insert(i, i * 10);
    }

    // HashSet
    let mut hash_set = HashSet::<u64, BuildHasherDefault<SimpleHasher>>::default();
    for i in 1..5 {
        hash_set.insert(i);
    }

    zzz(); // #break
}

fn zzz() {
    ()
}
<commit_msg>Add //ignore-macos to pretty-std-collections.rs<commit_after>// ignore-tidy-linelength
// ignore-windows failing on win32 bot
// ignore-freebsd: gdb package too new
// ignore-android: FIXME(#10381)
// ignore-macos: FIXME(#78665)
// compile-flags:-g

// The pretty printers being tested here require the patch from
// https://sourceware.org/bugzilla/show_bug.cgi?id=21763
// min-gdb-version: 8.1

// min-lldb-version: 310

// === GDB TESTS ===================================================================================

// gdb-command: run

// gdb-command: print btree_set
// gdb-check:$1 = BTreeSet(size=15) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}

// gdb-command: print empty_btree_set
// gdb-check:$2 = BTreeSet(size=0)

// gdb-command: print btree_map
// gdb-check:$3 = BTreeMap(size=15) = {[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7, [8] = 8, [9] = 9, [10] = 10, [11] = 11, [12] = 12, [13] = 13, [14] = 14}

// gdb-command: print empty_btree_map
// gdb-check:$4 = BTreeMap(size=0)

// gdb-command: print option_btree_map
// gdb-check:$5 = BTreeMap(size=2) = {[false] = [...], [true] = [...]}
// (abbreviated because both values vary wildly over gdb versions and/or linux distributions)

// gdb-command: print nasty_btree_map
// gdb-check:$6 = BTreeMap(size=15) = {[0] = pretty_std_collections::MyLeafNode (0), [...]}
// (abbreviated because it's boring but we need enough elements to include internal nodes)

// gdb-command: print zst_key_btree_map
// gdb-check:$7 = BTreeMap(size=1) = {[()] = 1}

// gdb-command: print zst_val_btree_map
// gdb-check:$8 = BTreeMap(size=1) = {[1] = ()}

// gdb-command: print zst_key_val_btree_map
// gdb-check:$9 = BTreeMap(size=1) = {[()] = ()}

// gdb-command: print vec_deque
// gdb-check:$10 = VecDeque(size=3) = {5, 3, 7}

// gdb-command: print vec_deque2
// gdb-check:$11 = VecDeque(size=7) = {2, 3, 4, 5, 6, 7, 8}

// gdb-command: print hash_map
// gdb-check:$12 = HashMap(size=4) = {[1] = 10, [2] = 20, [3] = 30, [4] = 40}

// gdb-command: print hash_set
// gdb-check:$13 = HashSet(size=4) = {1, 2, 3, 4}

// === LLDB TESTS ==================================================================================

// lldb-command:run

// lldb-command:print vec_deque
// lldbg-check:[...]$0 = size=3 { [0] = 5 [1] = 3 [2] = 7 }
// lldbr-check:(alloc::collections::vec_deque::VecDeque<i32>) vec_deque = size=3 = { [0] = 5 [1] = 3 [2] = 7 }

// lldb-command:print vec_deque2
// lldbg-check:[...]$1 = size=7 { [0] = 2 [1] = 3 [2] = 4 [3] = 5 [4] = 6 [5] = 7 [6] = 8 }
// lldbr-check:(alloc::collections::vec_deque::VecDeque<i32>) vec_deque2 = size=7 = { [0] = 2 [1] = 3 [2] = 4 [3] = 5 [4] = 6 [5] = 7 [6] = 8 }

// lldb-command:print hash_map
// lldbg-check:[...]$2 = size=4 { [0] = { 0 = 1 1 = 10 } [1] = { 0 = 2 1 = 20 } [2] = { 0 = 3 1 = 30 } [3] = { 0 = 4 1 = 40 } }
// lldbr-check:(std::collections::hash::map::HashMap<u64, u64, [...]>) hash_map = size=4 size=4 { [0] = { 0 = 1 1 = 10 } [1] = { 0 = 2 1 = 20 } [2] = { 0 = 3 1 = 30 } [3] = { 0 = 4 1 = 40 } }

// lldb-command:print hash_set
// lldbg-check:[...]$3 = size=4 { [0] = 1 [1] = 2 [2] = 3 [3] = 4 }
// lldbr-check:(std::collections::hash::set::HashSet<u64, [...]>) hash_set = size=4 { [0] = 1 [1] = 2 [2] = 3 [3] = 4 }

#![allow(unused_variables)]
use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::collections::HashMap;
use std::collections::HashSet;
use std::collections::VecDeque;
use std::hash::{BuildHasherDefault, Hasher};

struct MyLeafNode(i32); // helps to ensure we don't blindly replace substring "LeafNode"

#[derive(Default)]
struct SimpleHasher { hash: u64 }

impl Hasher for SimpleHasher {
    fn finish(&self) -> u64 { self.hash }
    fn write(&mut self, bytes: &[u8]) {}
    fn write_u64(&mut self, i: u64) { self.hash = i }
}

fn main() {
    // BTreeSet
    let mut btree_set = BTreeSet::new();
    for i in 0..15 {
        btree_set.insert(i);
    }

    let mut empty_btree_set: BTreeSet<i32> = BTreeSet::new();

    // BTreeMap
    let mut btree_map = BTreeMap::new();
    for i in 0..15 {
        btree_map.insert(i, i);
    }

    let mut empty_btree_map: BTreeMap<i32, u32> = BTreeMap::new();

    let mut option_btree_map: BTreeMap<bool, Option<bool>> = BTreeMap::new();
    option_btree_map.insert(false, None);
    option_btree_map.insert(true, Some(true));

    let mut nasty_btree_map: BTreeMap<i32, MyLeafNode> = BTreeMap::new();
    for i in 0..15 {
        nasty_btree_map.insert(i, MyLeafNode(i));
    }

    let mut zst_key_btree_map: BTreeMap<(), i32> = BTreeMap::new();
    zst_key_btree_map.insert((), 1);

    let mut zst_val_btree_map: BTreeMap<i32, ()> = BTreeMap::new();
    zst_val_btree_map.insert(1, ());

    let mut zst_key_val_btree_map: BTreeMap<(), ()> = BTreeMap::new();
    zst_key_val_btree_map.insert((), ());

    // VecDeque
    let mut vec_deque = VecDeque::new();
    vec_deque.push_back(5);
    vec_deque.push_back(3);
    vec_deque.push_back(7);

    // VecDeque where an element was popped.
    let mut vec_deque2 = VecDeque::new();
    for i in 1..8 {
        vec_deque2.push_back(i)
    }
    vec_deque2.pop_front();
    vec_deque2.push_back(8);

    // HashMap
    let mut hash_map = HashMap::<u64, u64, BuildHasherDefault<SimpleHasher>>::default();
    for i in 1..5 {
        hash_map.insert(i, i * 10);
    }

    // HashSet
    let mut hash_set = HashSet::<u64, BuildHasherDefault<SimpleHasher>>::default();
    for i in 1..5 {
        hash_set.insert(i);
    }

    zzz(); // #break
}

fn zzz() {
    ()
}
<|endoftext|>


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

#![feature(generators)]

fn bar<'a>() {
    let a: &'static str = "hi";
    let b: &'a str = a;

	|| {
		yield a;
		yield b;
	};
}

fn main() {}<commit_msg>Convert to spaces<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(generators)]

fn bar<'a>() {
    let a: &'static str = "hi";
    let b: &'a str = a;

    || {
        yield a;
        yield b;
    };
}

fn main() {}<|endoftext|>


<commit_before>// check-pass

#![feature(generic_associated_types)]

trait CallWithShim: Sized {
    type Shim<'s>
    where
        Self: 's;
}

#[derive(Clone)]
struct ShimMethod<T: CallWithShim + 'static>(pub &'static dyn for<'s> Fn(&'s mut T::Shim<'s>));

pub fn main() {}
<commit_msg>Additional tests (from jackh726)<commit_after>// check-pass

#![feature(generic_associated_types)]

trait CallWithShim: Sized {
    type Shim<'s>
    where
        Self: 's;
}

#[derive(Clone)]
struct ShimMethod<T: CallWithShim + 'static>(pub &'static dyn for<'s> Fn(&'s mut T::Shim<'s>));

trait CallWithShim2: Sized {
    type Shim<T>;
}

struct S<'s>(&'s ());

#[derive(Clone)]
struct ShimMethod2<T: CallWithShim2 + 'static>(pub &'static dyn for<'s> Fn(&'s mut T::Shim<S<'s>>));

trait Trait<'s, 't> {}

#[derive(Clone)]
struct ShimMethod3<T: CallWithShim2 + 'static>(
    pub &'static dyn for<'s> Fn(&'s mut T::Shim<dyn for<'t> Trait<'s, 't>>),
);

trait Trait2 {
    type As;
}

#[derive(Clone)]
struct ShimMethod4<T: Trait2 + 'static>(pub &'static dyn for<'s> Fn(&'s mut T::As));

pub fn main() {}
<|endoftext|>