<commit_before>// Copyright 2012 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.

use front::map as ast_map;
use session::{config, Session};
use syntax::ast::NodeId;
use syntax::attr;
use syntax::codemap::Span;
use syntax::entry::EntryPointType;
use rustc_front::hir::{Item, ItemFn};
use rustc_front::visit;
use rustc_front::visit::Visitor;

struct EntryContext<'a> {
    session: &'a Session,

    // The current depth in the ast
    depth: usize,

    // The top-level function called 'main'
    main_fn: Option<(NodeId, Span)>,

    // The function that has attribute named 'main'
    attr_main_fn: Option<(NodeId, Span)>,

    // The function that has the attribute 'start' on it
    start_fn: Option<(NodeId, Span)>,

    // The functions that one might think are 'main' but aren't, e.g.
    // main functions not defined at the top level. For diagnostics.
    non_main_fns: Vec<(NodeId, Span)> ,
}

impl<'a, 'v> Visitor<'v> for EntryContext<'a> {
    fn visit_item(&mut self, item: &Item) {
        self.depth += 1;
        find_item(item, self);
        self.depth -= 1;
    }
}

pub fn find_entry_point(session: &Session, ast_map: &ast_map::Map) {
    let any_exe = session.crate_types.borrow().iter().any(|ty| {
        *ty == config::CrateTypeExecutable
    });
    if !any_exe {
        // No need to find a main function
        return
    }

    // If the user wants no main function at all, then stop here.
    if attr::contains_name(&ast_map.krate().attrs, "no_main") {
        session.entry_type.set(Some(config::EntryNone));
        return
    }

    let mut ctxt = EntryContext {
        session: session,
        depth: 0,
        main_fn: None,
        attr_main_fn: None,
        start_fn: None,
        non_main_fns: Vec::new(),
    };

    visit::walk_crate(&mut ctxt, ast_map.krate());

    configure_main(&mut ctxt);
}

// Beware, this is duplicated in libsyntax/entry.rs, make sure to keep
// them in sync.
fn entry_point_type(item: &Item, depth: usize) -> EntryPointType {
    match item.node {
        ItemFn(..) => {
            if attr::contains_name(&item.attrs, "start") {
                EntryPointType::Start
            } else if attr::contains_name(&item.attrs, "main") {
                EntryPointType::MainAttr
            } else if item.name.as_str() == "main" {
                if depth == 1 {
                    // This is a top-level function so can be 'main'
                    EntryPointType::MainNamed
                } else {
                    EntryPointType::OtherMain
                }
            } else {
                EntryPointType::None
            }
        }
        _ => EntryPointType::None,
    }
}

fn find_item(item: &Item, ctxt: &mut EntryContext) {
    match entry_point_type(item, ctxt.depth) {
        EntryPointType::MainNamed => {
            if ctxt.main_fn.is_none() {
                ctxt.main_fn = Some((item.id, item.span));
            } else {
                span_err!(ctxt.session, item.span, E0136,
                          "multiple 'main' functions");
            }
        },
        EntryPointType::OtherMain => {
            ctxt.non_main_fns.push((item.id, item.span));
        },
        EntryPointType::MainAttr => {
            if ctxt.attr_main_fn.is_none() {
                ctxt.attr_main_fn = Some((item.id, item.span));
            } else {
                span_err!(ctxt.session, item.span, E0137,
                          "multiple functions with a #[main] attribute");
            }
        },
        EntryPointType::Start => {
            if ctxt.start_fn.is_none() {
                ctxt.start_fn = Some((item.id, item.span));
            } else {
                span_err!(ctxt.session, item.span, E0138,
                          "multiple 'start' functions");
            }
        },
        EntryPointType::None => ()
    }

    visit::walk_item(ctxt, item);
}

fn configure_main(this: &mut EntryContext) {
    if this.start_fn.is_some() {
        *this.session.entry_fn.borrow_mut() = this.start_fn;
        this.session.entry_type.set(Some(config::EntryStart));
    } else if this.attr_main_fn.is_some() {
        *this.session.entry_fn.borrow_mut() = this.attr_main_fn;
        this.session.entry_type.set(Some(config::EntryMain));
    } else if this.main_fn.is_some() {
        *this.session.entry_fn.borrow_mut() = this.main_fn;
        this.session.entry_type.set(Some(config::EntryMain));
    } else {
        // No main function
        this.session.err("main function not found");
        if !this.non_main_fns.is_empty() {
            // There were some functions named 'main' though. Try to give the user a hint.
            this.session.note("the main function must be defined at the crate level \
                               but you have one or more functions named 'main' that are not \
                               defined at the crate level. Either move the definition or \
                               attach the `#[main]` attribute to override this behavior.");
            for &(_, span) in &this.non_main_fns {
                this.session.span_note(span, "here is a function named 'main'");
            }
            this.session.abort_if_errors();
        }
    }
}
<commit_msg>Port entry code to `visit_all_items` -- since this was tracking whether the main fn appeared at the top level, if now consults the `DefPath` to get this information<commit_after>// Copyright 2012 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.

use front::map as ast_map;
use middle::def_id::{CRATE_DEF_INDEX};
use session::{config, Session};
use syntax::ast::NodeId;
use syntax::attr;
use syntax::codemap::Span;
use syntax::entry::EntryPointType;
use rustc_front::hir::{Item, ItemFn};
use rustc_front::intravisit::Visitor;

struct EntryContext<'a, 'tcx: 'a> {
    session: &'a Session,

    map: &'a ast_map::Map<'tcx>,

    // The top-level function called 'main'
    main_fn: Option<(NodeId, Span)>,

    // The function that has attribute named 'main'
    attr_main_fn: Option<(NodeId, Span)>,

    // The function that has the attribute 'start' on it
    start_fn: Option<(NodeId, Span)>,

    // The functions that one might think are 'main' but aren't, e.g.
    // main functions not defined at the top level. For diagnostics.
    non_main_fns: Vec<(NodeId, Span)> ,
}

impl<'a, 'tcx> Visitor<'tcx> for EntryContext<'a, 'tcx> {
    fn visit_item(&mut self, item: &'tcx Item) {
        let def_id = self.map.local_def_id(item.id);
        let def_key = self.map.def_key(def_id);
        let at_root = def_key.parent == Some(CRATE_DEF_INDEX);
        find_item(item, self, at_root);
    }
}

pub fn find_entry_point(session: &Session, ast_map: &ast_map::Map) {
    let any_exe = session.crate_types.borrow().iter().any(|ty| {
        *ty == config::CrateTypeExecutable
    });
    if !any_exe {
        // No need to find a main function
        return
    }

    // If the user wants no main function at all, then stop here.
    if attr::contains_name(&ast_map.krate().attrs, "no_main") {
        session.entry_type.set(Some(config::EntryNone));
        return
    }

    let mut ctxt = EntryContext {
        session: session,
        map: ast_map,
        main_fn: None,
        attr_main_fn: None,
        start_fn: None,
        non_main_fns: Vec::new(),
    };

    ast_map.krate().visit_all_items(&mut ctxt);

    configure_main(&mut ctxt);
}

// Beware, this is duplicated in libsyntax/entry.rs, make sure to keep
// them in sync.
fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType {
    match item.node {
        ItemFn(..) => {
            if attr::contains_name(&item.attrs, "start") {
                EntryPointType::Start
            } else if attr::contains_name(&item.attrs, "main") {
                EntryPointType::MainAttr
            } else if item.name.as_str() == "main" {
                if at_root {
                    // This is a top-level function so can be 'main'
                    EntryPointType::MainNamed
                } else {
                    EntryPointType::OtherMain
                }
            } else {
                EntryPointType::None
            }
        }
        _ => EntryPointType::None,
    }
}

fn find_item(item: &Item, ctxt: &mut EntryContext, at_root: bool) {
    match entry_point_type(item, at_root) {
        EntryPointType::MainNamed => {
            if ctxt.main_fn.is_none() {
                ctxt.main_fn = Some((item.id, item.span));
            } else {
                span_err!(ctxt.session, item.span, E0136,
                          "multiple 'main' functions");
            }
        },
        EntryPointType::OtherMain => {
            ctxt.non_main_fns.push((item.id, item.span));
        },
        EntryPointType::MainAttr => {
            if ctxt.attr_main_fn.is_none() {
                ctxt.attr_main_fn = Some((item.id, item.span));
            } else {
                span_err!(ctxt.session, item.span, E0137,
                          "multiple functions with a #[main] attribute");
            }
        },
        EntryPointType::Start => {
            if ctxt.start_fn.is_none() {
                ctxt.start_fn = Some((item.id, item.span));
            } else {
                span_err!(ctxt.session, item.span, E0138,
                          "multiple 'start' functions");
            }
        },
        EntryPointType::None => ()
    }
}

fn configure_main(this: &mut EntryContext) {
    if this.start_fn.is_some() {
        *this.session.entry_fn.borrow_mut() = this.start_fn;
        this.session.entry_type.set(Some(config::EntryStart));
    } else if this.attr_main_fn.is_some() {
        *this.session.entry_fn.borrow_mut() = this.attr_main_fn;
        this.session.entry_type.set(Some(config::EntryMain));
    } else if this.main_fn.is_some() {
        *this.session.entry_fn.borrow_mut() = this.main_fn;
        this.session.entry_type.set(Some(config::EntryMain));
    } else {
        // No main function
        this.session.err("main function not found");
        if !this.non_main_fns.is_empty() {
            // There were some functions named 'main' though. Try to give the user a hint.
            this.session.note("the main function must be defined at the crate level \
                               but you have one or more functions named 'main' that are not \
                               defined at the crate level. Either move the definition or \
                               attach the `#[main]` attribute to override this behavior.");
            for &(_, span) in &this.non_main_fns {
                this.session.span_note(span, "here is a function named 'main'");
            }
            this.session.abort_if_errors();
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Formatting<commit_after><|endoftext|>


<commit_before><commit_msg>add toggle active to quests<commit_after><|endoftext|>


<commit_before>use audio::wav::*;

use programs::common::*;

use graphics::bmp::*;

pub struct Sprite {
    point: Point,
    image: BMP
}

impl Sprite {
    pub fn draw(&self, content: &mut Display){
        content.image_alpha(self.point, self.image.data, self.image.size);
    }
}

pub struct Application;

impl SessionItem for Application {
    fn main(&mut self, url: URL){
        let mut window = Window::new(Point::new((rand() % 400 + 50) as isize, (rand() % 300 + 50) as isize), Size::new(640, 480), "Example Game (Loading)".to_string());

        let mut player;
        {
            let mut resource = URL::from_string(&"file:///game/ninjaroofront.bmp".to_string()).open();
            let mut bytes: Vec<u8> = Vec::new();
            resource.read_to_end(&mut bytes);
            player = Sprite {
                point: Point::new(200, 200),
                image: unsafe{ BMP::from_data(bytes.as_ptr() as usize) }
            };
        }

        window.title = "Example Game".to_string();

        let sound;
        {
            let mut resource = URL::from_string(&"file:///game/wilhelm.wav".to_string()).open();
            let mut bytes: Vec<u8> = Vec::new();
            resource.read_to_end(&mut bytes);

            sound = WAV::from_data(&bytes);
        }

        let mut keys: Vec<u8> = Vec::new();
        let mut redraw = true;
        let mut running = true;
        while running {
            loop {
                match window.poll() {
                    EventOption::Key(key_event) => {
                        if key_event.pressed {
                            match key_event.scancode {
                                K_ESC => {
                                    running = false;
                                    break;
                                },
                                K_CTRL => {
                                    let mut resource = URL::from_string(&"audio://".to_string()).open();
                                    resource.write(sound.data.as_slice());
                                },
                                _ => ()
                            }

                            let mut found = false;
                            for key in keys.iter() {
                                if *key == key_event.scancode {
                                    found = true;
                                    break;
                                }
                            }
                            if ! found {
                                keys.push(key_event.scancode);
                            }
                        }else{
                            let mut i = 0;
                            while i < keys.len() {
                                let mut remove = false;
                                if let Option::Some(key) = keys.get(i) {
                                    if *key == key_event.scancode {
                                        remove = true;
                                    }
                                }
                                if remove {
                                    keys.remove(i);
                                }else{
                                    i += 1;
                                }
                            }
                        }
                    },
                    EventOption::None => break,
                    _ => ()
                }
            }

            for key in keys.iter() {
                match *key {
                    K_LEFT => {
                        player.point.x = max(0, player.point.x - 1);
                        redraw = true;
                    },
                    K_RIGHT => {
                        player.point.x = min(window.content.width as isize - 1, player.point.x + 1);
                        redraw = true;
                    },
                    K_UP => {
                        player.point.y = max(0, player.point.y - 1);
                        redraw = true;
                    },
                    K_DOWN => {
                        player.point.y = min(window.content.height as isize - 1, player.point.y + 1);
                        redraw = true;
                    },
                    _ => ()
                }
            }

            if redraw {
                redraw = false;

                let content = &mut window.content;
                content.set(Color::new(128, 128, 255));

                player.draw(content);

                content.flip();

                RedrawEvent {
                    redraw: REDRAW_ALL
                }.trigger();
            }

            Duration::new(0, 1000000000/120).sleep();
        }
    }
}

impl Application {
    pub fn new() -> Application {
        Application
    }
}
<commit_msg>Wait for other audio processes<commit_after>use audio::wav::*;

use programs::common::*;

use graphics::bmp::*;

pub struct Sprite {
    point: Point,
    image: BMP
}

impl Sprite {
    pub fn draw(&self, content: &mut Display){
        content.image_alpha(self.point, self.image.data, self.image.size);
    }
}

pub struct Application;

impl SessionItem for Application {
    fn main(&mut self, url: URL){
        let mut window = Window::new(Point::new((rand() % 400 + 50) as isize, (rand() % 300 + 50) as isize), Size::new(640, 480), "Example Game (Loading)".to_string());
        RedrawEvent { redraw: REDRAW_ALL }.trigger();

        let mut audio = URL::from_string(&"audio://".to_string()).open();

        let mut player;
        {
            let mut resource = URL::from_string(&"file:///game/ninjaroofront.bmp".to_string()).open();
            let mut bytes: Vec<u8> = Vec::new();
            resource.read_to_end(&mut bytes);
            player = Sprite {
                point: Point::new(200, 200),
                image: unsafe{ BMP::from_data(bytes.as_ptr() as usize) }
            };
        }

        let sound;
        {
            let mut resource = URL::from_string(&"file:///game/wilhelm.wav".to_string()).open();
            let mut bytes: Vec<u8> = Vec::new();
            resource.read_to_end(&mut bytes);

            sound = WAV::from_data(&bytes);
        }

        window.title = "Example Game".to_string();
        RedrawEvent { redraw: REDRAW_ALL }.trigger();

        let mut keys: Vec<u8> = Vec::new();
        let mut redraw = true;
        let mut running = true;
        while running {
            loop {
                match window.poll() {
                    EventOption::Key(key_event) => {
                        if key_event.pressed {
                            match key_event.scancode {
                                K_ESC => {
                                    running = false;
                                    break;
                                },
                                K_DEL => {
                                    window.title = "Example Game (Screaming)".to_string();
                                    RedrawEvent { redraw: REDRAW_ALL }.trigger();
                                    audio.write(sound.data.as_slice());
                                    window.title = "Example Game".to_string();
                                    RedrawEvent { redraw: REDRAW_ALL }.trigger();
                                },
                                _ => ()
                            }

                            let mut found = false;
                            for key in keys.iter() {
                                if *key == key_event.scancode {
                                    found = true;
                                    break;
                                }
                            }
                            if ! found {
                                keys.push(key_event.scancode);
                            }
                        }else{
                            let mut i = 0;
                            while i < keys.len() {
                                let mut remove = false;
                                if let Option::Some(key) = keys.get(i) {
                                    if *key == key_event.scancode {
                                        remove = true;
                                    }
                                }
                                if remove {
                                    keys.remove(i);
                                }else{
                                    i += 1;
                                }
                            }
                        }
                    },
                    EventOption::None => break,
                    _ => ()
                }
            }

            for key in keys.iter() {
                match *key {
                    K_LEFT => {
                        player.point.x = max(0, player.point.x - 1);
                        redraw = true;
                    },
                    K_RIGHT => {
                        player.point.x = min(window.content.width as isize - 1, player.point.x + 1);
                        redraw = true;
                    },
                    K_UP => {
                        player.point.y = max(0, player.point.y - 1);
                        redraw = true;
                    },
                    K_DOWN => {
                        player.point.y = min(window.content.height as isize - 1, player.point.y + 1);
                        redraw = true;
                    },
                    _ => ()
                }
            }

            if redraw {
                redraw = false;

                let content = &mut window.content;
                content.set(Color::new(128, 128, 255));

                player.draw(content);

                content.flip();
                RedrawEvent { redraw: REDRAW_ALL }.trigger();
            }

            Duration::new(0, 1000000000/120).sleep();
        }

        window.title = "Example Game (Closing)".to_string();
        RedrawEvent { redraw: REDRAW_ALL }.trigger();

        {
            let mut resource = URL::from_string(&"file:///game/game_over.wav".to_string()).open();
            let mut bytes: Vec<u8> = Vec::new();
            resource.read_to_end(&mut bytes);

            let game_over = WAV::from_data(&bytes);
            audio.write(game_over.data.as_slice());
        }
    }
}

impl Application {
    pub fn new() -> Application {
        Application
    }
}
<|endoftext|>


<commit_before><commit_msg>Add test for issue #16994.<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(rustc_attrs)]

fn cb<'a,T>(_x: Box<Fn((&'a i32, &'a (Vec<&'static i32>, bool))) -> T>) -> T {
    panic!()
}

#[rustc_error]
fn main() { //~ ERROR compilation successful
    cb(Box::new(|(k, &(ref v, b))| (*k, v.clone(), b)));
}
<|endoftext|>


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

fn foo<U>(t: U) {
    let y = t();
//~^ ERROR: expected function, found `U`
}

struct Bar;

pub fn some_func() {
    let f = Bar();
//~^ ERROR: expected function, found `Bar`
}

fn main() {
    foo(|| { 1 });
}
<|endoftext|>


<commit_before><commit_msg>Create iterators4.rs<commit_after>pub fn factorial(num: u64) -> u64 {
    // Complete this function to return factorial of num
    // Do not use:
    // - return
    // For extra fun don't use:
    // - imperative style loops (for, while)
    // - additional variables
    // For the most fun don't use:
    // - recursion
    // Scroll down for hints.
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn factorial_of_1() {
        assert_eq!(1, factorial(1));
    }
    #[test]
    fn factorial_of_2() {
        assert_eq!(2, factorial(2));
    }

    #[test]
    fn factorial_of_4() {
        assert_eq!(24, factorial(4));
    }
}

// In an imperative language you might write a for loop to iterate through
// multiply the values into a mutable variable. Or you might write code more
// functionally with recursion and a match clause. But you can also use ranges
// and iterators to solve this in rust.
<|endoftext|>


<commit_before>use common::debug::*;
use common::pci::*;

use programs::session::*;

pub struct XHCI {
    pub bus: usize,
    pub slot: usize,
    pub func: usize,
    pub base: usize,
    pub memory_mapped: bool,
    pub irq: u8
}

impl SessionDevice for XHCI {
    fn handle(&mut self, irq: u8){
        if irq == self.irq {
            d("XHCI handle");
        }
    }
}

impl XHCI {
    pub unsafe fn init(&self){
        d("XHCI on: ");
        dh(self.base);
        if self.memory_mapped {
            d(" memory mapped");
        }else{
            d(" port mapped");
        }
        d(" IRQ: ");
        dbh(self.irq);
        dl();

        pci_write(self.bus, self.slot, self.func, 0x04, pci_read(self.bus, self.slot, self.func, 0x04) | (1 << 2)); // Bus mastering

        //let base = self.base as u16;
    }
}
<commit_msg>WIP XHCI<commit_after>use common::debug::*;
use common::pci::*;

use programs::session::*;

pub struct XHCI {
    pub bus: usize,
    pub slot: usize,
    pub func: usize,
    pub base: usize,
    pub memory_mapped: bool,
    pub irq: u8
}

impl SessionDevice for XHCI {
    fn handle(&mut self, irq: u8){
        if irq == self.irq {
            d("XHCI handle");
        }
    }
}

impl XHCI {
    pub unsafe fn init(&self){
        d("XHCI on: ");
        dh(self.base);
        if self.memory_mapped {
            d(" memory mapped");
        }else{
            d(" port mapped");
        }
        d(" IRQ: ");
        dbh(self.irq);
        dl();

        pci_write(self.bus, self.slot, self.func, 0x04, pci_read(self.bus, self.slot, self.func, 0x04) | (1 << 2)); // Bus master

        let cap_base = self.base;
        let op_base = cap_base + *(cap_base as *mut u8) as usize;
        let db_base = cap_base + *((cap_base + 0x14) as *mut u32) as usize;
        let rt_base = cap_base + *((cap_base + 0x18) as *mut u32) as usize;

        d("CAP_BASE: ");
        dh(cap_base);

        d(" OP_BASE: ");
        dh(op_base);

        d(" DB_BASE: ");
        dh(db_base);

        d(" RT_BASE: ");
        dh(rt_base);
        dl();

        //Set FLADJ Frame Length Adjustment (optional?)
        //Set I/O memory maps (optional?)

        //Wait until the Controller Not Ready flag in USBSTS is 0
        let usbsts = (op_base + 0x04) as *mut u32;
        while *usbsts & (1 << 11) == (1 << 11) {
            d("Controller Not Ready\n");
        }
        d("Controller Ready ");
        dh(*usbsts as usize);
        dl();

        //Set Run/Stop to 0
        let usbcmd = op_base as *mut u32;
        *usbcmd = *usbcmd & 0xFFFFFFFE;

        while *usbsts & 1 == 0 {
            d("Command Not Ready\n");
        }
        d("Command Ready ");
        dh(*usbcmd as usize);
        dl();

        //Program the Max Device Slots Enabled in the CONFIG register
        let hcsparams1 = (cap_base + 0x04) as *const u32;

        d("Enabling Slots ");
        dd((*hcsparams1 & 0xFF) as usize);
        dl();

        let config = (op_base + 0x38) as *mut u32;
        dh(*config as usize);
        *config = *hcsparams1 & 0xFF;
        d(" ");
        dh(*config as usize);
        dl();

        //Program the Device Context Base Address Array Pointer with a pointer to the Device Context Base Address Array
        //Device the Command Ring Dequeue Pointer by programming the Command ring Control register with a pointer to the first TRB
        //Initialize interrupts (optional)
            //Allocate and initalize the MSI-X Message Table, setting the message address and message data, and enable the vectors. At least table vector entry 0 should be initialized
            //Allocate and initialize the MSI-X Pending Bit Array
            //Point the Table Offset and PBA Offsets in the MSI-X Capability Structure to the MSI-X Message Control Table and Pending Bit Array
            //Initialize the Message Control register in the MSI-X Capability Structure
            //Initialize each active interrupter by:
                //TODO: Pull from page 72
        //Write the USBCMD to turn on the host controller by setting Run/Stop to 1
    }
}
<|endoftext|>


<commit_before><commit_msg>Add an integration test.<commit_after>extern crate littletest;

use littletest::{Runnable, TestResult, TestRunner};

struct TestCase {
    result: TestResult
}

impl TestCase {
    fn new(result: TestResult) -> TestCase {
        TestCase {
            result: result
        }
    }
}

impl Runnable for TestCase {
    fn run(&self) -> TestResult {
        match self.result {
            TestResult::Pass => TestResult::Pass,
            TestResult::Fail => TestResult::Fail,
            TestResult::Error => TestResult::Error,
            TestResult::Skipped => TestResult::Skipped
        }
    }
}

#[test]
fn it_works() {
    let tests = vec![TestResult::Pass];
    let runnables: Vec<Box<Runnable>> = tests
        .into_iter()
        .map(|result| Box::new(TestCase::new(result)) as Box<Runnable>)
        .collect();

    let runner = TestRunner;
    runner.run(&runnables);
}
<|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.

use std::fmt;
use std::ops::{Deref, Range};

use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
use rustc_data_structures::sync::Lrc;

#[derive(Clone)]
pub struct RcVec<T> {
    data: Lrc<Vec<T>>,
    offset: u32,
    len: u32,
}

impl<T> RcVec<T> {
    pub fn new(mut vec: Vec<T>) -> Self {
        // By default, constructing RcVec from Vec gives it just enough capacity
        // to hold the initial elements. Callers that anticipate needing to
        // extend the vector may prefer RcVec::new_preserving_capacity.
        vec.shrink_to_fit();

        RcVec {
            offset: 0,
            len: vec.len() as u32,
            data: Lrc::new(vec),
        }
    }

    pub fn new_preserving_capacity(vec: Vec<T>) -> Self {
        RcVec {
            offset: 0,
            len: vec.len() as u32,
            data: Lrc::new(vec),
        }
    }

    pub fn sub_slice(&self, range: Range<usize>) -> Self {
        RcVec {
            data: self.data.clone(),
            offset: self.offset + range.start as u32,
            len: (range.end - range.start) as u32,
        }
    }

    /// If this RcVec has exactly one strong reference, returns ownership of the
    /// underlying vector. Otherwise returns self unmodified.
    pub fn try_unwrap(self) -> Result<Vec<T>, Self> {
        match Lrc::try_unwrap(self.data) {
            // If no other RcVec shares ownership of this data.
            Ok(mut vec) => {
                // Drop any elements after our view of the data.
                vec.truncate(self.offset as usize + self.len as usize);
                // Drop any elements before our view of the data.
                if self.offset != 0 {
                    vec.drain(..self.offset as usize);
                }
                Ok(vec)
            }

            // If the data is shared.
            Err(data) => Err(RcVec { data, ..self }),
        }
    }
}

impl<T> Deref for RcVec<T> {
    type Target = [T];
    fn deref(&self) -> &[T] {
        &self.data[self.offset as usize..(self.offset + self.len) as usize]
    }
}

impl<T: fmt::Debug> fmt::Debug for RcVec<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.deref(), f)
    }
}

impl<CTX, T> HashStable<CTX> for RcVec<T>
where
    T: HashStable<CTX>,
{
    fn hash_stable<W: StableHasherResult>(&self, hcx: &mut CTX, hasher: &mut StableHasher<W>) {
        (**self).hash_stable(hcx, hasher);
    }
}
<commit_msg>Address review of RcVec<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.

use std::fmt;
use std::ops::{Deref, Range};

use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
use rustc_data_structures::sync::Lrc;

#[derive(Clone)]
pub struct RcVec<T> {
    data: Lrc<Vec<T>>,
    offset: u32,
    len: u32,
}

impl<T> RcVec<T> {
    pub fn new(mut vec: Vec<T>) -> Self {
        // By default, constructing RcVec from Vec gives it just enough capacity
        // to hold the initial elements. Callers that anticipate needing to
        // extend the vector may prefer RcVec::new_preserving_capacity.
        vec.shrink_to_fit();
        Self::new_preserving_capacity(vec)
    }

    pub fn new_preserving_capacity(vec: Vec<T>) -> Self {
        RcVec {
            offset: 0,
            len: vec.len() as u32,
            data: Lrc::new(vec),
        }
    }

    pub fn sub_slice(&self, range: Range<usize>) -> Self {
        RcVec {
            data: self.data.clone(),
            offset: self.offset + range.start as u32,
            len: (range.end - range.start) as u32,
        }
    }

    /// If this RcVec has exactly one strong reference, returns ownership of the
    /// underlying vector. Otherwise returns self unmodified.
    pub fn try_unwrap(self) -> Result<Vec<T>, Self> {
        match Lrc::try_unwrap(self.data) {
            // If no other RcVec shares ownership of this data.
            Ok(mut vec) => {
                // Drop any elements after our view of the data.
                vec.truncate(self.offset as usize + self.len as usize);
                // Drop any elements before our view of the data. Do this after
                // the `truncate` so that elements past the end of our view do
                // not need to be copied around.
                vec.drain(..self.offset as usize);
                Ok(vec)
            }

            // If the data is shared.
            Err(data) => Err(RcVec { data, ..self }),
        }
    }
}

impl<T> Deref for RcVec<T> {
    type Target = [T];
    fn deref(&self) -> &[T] {
        &self.data[self.offset as usize..(self.offset + self.len) as usize]
    }
}

impl<T: fmt::Debug> fmt::Debug for RcVec<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.deref(), f)
    }
}

impl<CTX, T> HashStable<CTX> for RcVec<T>
where
    T: HashStable<CTX>,
{
    fn hash_stable<W: StableHasherResult>(&self, hcx: &mut CTX, hasher: &mut StableHasher<W>) {
        (**self).hash_stable(hcx, hasher);
    }
}
<|endoftext|>


<commit_before><commit_msg>fix(Usage): fixes a bug where required args aren't filtered properly<commit_after><|endoftext|>


<commit_before><commit_msg>Add run-pass test for assignment to static mut<commit_after>// Copyright 2016 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.

// Test taken from #45641 (https://github.com/rust-lang/rust/issues/45641)

// ignore-tidy-linelength
// revisions: ast mir
//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir

static mut Y: u32 = 0;

unsafe fn should_ok() {
    Y = 1;
}

fn main() {}<|endoftext|>


<commit_before><commit_msg>Add cast example<commit_after>fn main() {
    let decimal = 65.4321_f32;

    // Error! No implicit conversion
    // let integer: u8 = decimal;
    // FIXME ^ Comment out this line

    // Explicit conversion
    let integer = decimal as u8;
    let character = integer as char;

    println!("Casting: {} -> {} -> {}", decimal, integer, character);

    // when casting any value to an unsigned type, T,
    // std::T::MAX + 1 is added or subtracted until the value
    // fits into the new type

    // 1000 already fits in a u16
    println!("1000 as a u16 is: {}", 1000 as u16);

    // 1000 - 256 - 256 = 232
    println!("1000 as a u8 is : {}", 1000 as u8);
    // -1 + 256 = 255
    println!("  -1 as a u8 is : {}", (-1i8) as u8);

    // For positive numbers, this is the same as the modulus
    println!("1000 mod 256 is : {}", 1000 % 256);

    // When casting to a signed type, the result is the same as
    // first casting to the corresponding unsigned type then
    // taking the two's complement.

    // Unless it already fits, of course.
    println!(" 128 as a i16 is: {}", 128 as i16);
    // 128 as u8 -> 128, whose two's complement in eight bits is:
    println!(" 128 as a i8 is : {}", 128 as i8);

    // repeating the example above
    // 1000 as u8 -> 232
    println!("1000 as a i8 is : {}", 1000 as i8);
    // and the two's complement of 232 is -24
    println!(" 232 as a i8 is : {}", 232 as i8);
}
<|endoftext|>


<commit_before>// Copyright 2014 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.

use libc;
use cell::UnsafeCell;
use sync::atomic::{AtomicUsize, Ordering};

pub struct RWLock {
    inner: UnsafeCell<libc::pthread_rwlock_t>,
    write_locked: UnsafeCell<bool>,
    num_readers: AtomicUsize,
}

unsafe impl Send for RWLock {}
unsafe impl Sync for RWLock {}

impl RWLock {
    pub const fn new() -> RWLock {
        RWLock {
            inner: UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER),
            write_locked: UnsafeCell::new(false),
            num_readers: AtomicUsize::new(0),
        }
    }
    #[inline]
    pub unsafe fn read(&self) {
        let r = libc::pthread_rwlock_rdlock(self.inner.get());

        // According to the pthread_rwlock_rdlock spec, this function **may**
        // fail with EDEADLK if a deadlock is detected. On the other hand
        // pthread mutexes will *never* return EDEADLK if they are initialized
        // as the "fast" kind (which ours always are). As a result, a deadlock
        // situation may actually return from the call to pthread_rwlock_rdlock
        // instead of blocking forever (as mutexes and Windows rwlocks do). Note
        // that not all unix implementations, however, will return EDEADLK for
        // their rwlocks.
        //
        // We roughly maintain the deadlocking behavior by panicking to ensure
        // that this lock acquisition does not succeed.
        //
        // We also check whether this lock is already write locked. This
        // is only possible if it was write locked by the current thread and
        // the implementation allows recursive locking. The POSIX standard
        // doesn't require recursively locking a rwlock to deadlock, but we can't
        // allow that because it could lead to aliasing issues.
        if r == libc::EAGAIN {
            panic!("rwlock maximum reader count exceeded");
        } else if r == libc::EDEADLK || *self.write_locked.get() {
            if r == 0 {
                self.raw_unlock();
            }
            panic!("rwlock read lock would result in deadlock");
        } else {
            debug_assert_eq!(r, 0);
            self.num_readers.fetch_add(1, Ordering::Relaxed);
        }
    }
    #[inline]
    pub unsafe fn try_read(&self) -> bool {
        let r = libc::pthread_rwlock_tryrdlock(self.inner.get());
        if r == 0 {
            if *self.write_locked.get() {
                self.raw_unlock();
                false
            } else {
                self.num_readers.fetch_add(1, Ordering::Relaxed);
                true
            }
        } else {
            false
        }
    }
    #[inline]
    pub unsafe fn write(&self) {
        let r = libc::pthread_rwlock_wrlock(self.inner.get());
        // See comments above for why we check for EDEADLK and write_locked. We
        // also need to check that num_readers is 0.
        if r == libc::EDEADLK || *self.write_locked.get() ||
           self.num_readers.load(Ordering::Relaxed) != 0 {
            if r == 0 {
                self.raw_unlock();
            }
            panic!("rwlock write lock would result in deadlock");
        } else {
            debug_assert_eq!(r, 0);
        }
        *self.write_locked.get() = true;
    }
    #[inline]
    pub unsafe fn try_write(&self) -> bool {
        let r = libc::pthread_rwlock_trywrlock(self.inner.get());
        if r == 0 {
            if *self.write_locked.get() || self.num_readers.load(Ordering::Relaxed) != 0 {
                self.raw_unlock();
                false
            } else {
                *self.write_locked.get() = true;
                true
            }
        } else {
            false
        }
    }
    #[inline]
    unsafe fn raw_unlock(&self) {
        let r = libc::pthread_rwlock_unlock(self.inner.get());
        debug_assert_eq!(r, 0);
    }
    #[inline]
    pub unsafe fn read_unlock(&self) {
        debug_assert!(!*self.write_locked.get());
        self.num_readers.fetch_sub(1, Ordering::Relaxed);
        self.raw_unlock();
    }
    #[inline]
    pub unsafe fn write_unlock(&self) {
        debug_assert_eq!(self.num_readers.load(Ordering::Relaxed), 0);
        debug_assert!(*self.write_locked.get());
        *self.write_locked.get() = false;
        self.raw_unlock();
    }
    #[inline]
    pub unsafe fn destroy(&self) {
        let r = libc::pthread_rwlock_destroy(self.inner.get());
        // On DragonFly pthread_rwlock_destroy() returns EINVAL if called on a
        // rwlock that was just initialized with
        // libc::PTHREAD_RWLOCK_INITIALIZER. Once it is used (locked/unlocked)
        // or pthread_rwlock_init() is called, this behaviour no longer occurs.
        if cfg!(target_os = "dragonfly") {
            debug_assert!(r == 0 || r == libc::EINVAL);
        } else {
            debug_assert_eq!(r, 0);
        }
    }
}
<commit_msg>Rollup merge of #55865 - RalfJung:unix-rwlock, r=alexcrichton<commit_after>// Copyright 2014 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.

use libc;
use cell::UnsafeCell;
use sync::atomic::{AtomicUsize, Ordering};

pub struct RWLock {
    inner: UnsafeCell<libc::pthread_rwlock_t>,
    write_locked: UnsafeCell<bool>, // guarded by the `inner` RwLock
    num_readers: AtomicUsize,
}

unsafe impl Send for RWLock {}
unsafe impl Sync for RWLock {}

impl RWLock {
    pub const fn new() -> RWLock {
        RWLock {
            inner: UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER),
            write_locked: UnsafeCell::new(false),
            num_readers: AtomicUsize::new(0),
        }
    }
    #[inline]
    pub unsafe fn read(&self) {
        let r = libc::pthread_rwlock_rdlock(self.inner.get());

        // According to the pthread_rwlock_rdlock spec, this function **may**
        // fail with EDEADLK if a deadlock is detected. On the other hand
        // pthread mutexes will *never* return EDEADLK if they are initialized
        // as the "fast" kind (which ours always are). As a result, a deadlock
        // situation may actually return from the call to pthread_rwlock_rdlock
        // instead of blocking forever (as mutexes and Windows rwlocks do). Note
        // that not all unix implementations, however, will return EDEADLK for
        // their rwlocks.
        //
        // We roughly maintain the deadlocking behavior by panicking to ensure
        // that this lock acquisition does not succeed.
        //
        // We also check whether this lock is already write locked. This
        // is only possible if it was write locked by the current thread and
        // the implementation allows recursive locking. The POSIX standard
        // doesn't require recursively locking a rwlock to deadlock, but we can't
        // allow that because it could lead to aliasing issues.
        if r == libc::EAGAIN {
            panic!("rwlock maximum reader count exceeded");
        } else if r == libc::EDEADLK || (r == 0 && *self.write_locked.get()) {
            if r == 0 {
                self.raw_unlock();
            }
            panic!("rwlock read lock would result in deadlock");
        } else {
            assert_eq!(r, 0);
            self.num_readers.fetch_add(1, Ordering::Relaxed);
        }
    }
    #[inline]
    pub unsafe fn try_read(&self) -> bool {
        let r = libc::pthread_rwlock_tryrdlock(self.inner.get());
        if r == 0 {
            if *self.write_locked.get() {
                self.raw_unlock();
                false
            } else {
                self.num_readers.fetch_add(1, Ordering::Relaxed);
                true
            }
        } else {
            false
        }
    }
    #[inline]
    pub unsafe fn write(&self) {
        let r = libc::pthread_rwlock_wrlock(self.inner.get());
        // See comments above for why we check for EDEADLK and write_locked. We
        // also need to check that num_readers is 0.
        if r == libc::EDEADLK || *self.write_locked.get() ||
           self.num_readers.load(Ordering::Relaxed) != 0 {
            if r == 0 {
                self.raw_unlock();
            }
            panic!("rwlock write lock would result in deadlock");
        } else {
            debug_assert_eq!(r, 0);
        }
        *self.write_locked.get() = true;
    }
    #[inline]
    pub unsafe fn try_write(&self) -> bool {
        let r = libc::pthread_rwlock_trywrlock(self.inner.get());
        if r == 0 {
            if *self.write_locked.get() || self.num_readers.load(Ordering::Relaxed) != 0 {
                self.raw_unlock();
                false
            } else {
                *self.write_locked.get() = true;
                true
            }
        } else {
            false
        }
    }
    #[inline]
    unsafe fn raw_unlock(&self) {
        let r = libc::pthread_rwlock_unlock(self.inner.get());
        debug_assert_eq!(r, 0);
    }
    #[inline]
    pub unsafe fn read_unlock(&self) {
        debug_assert!(!*self.write_locked.get());
        self.num_readers.fetch_sub(1, Ordering::Relaxed);
        self.raw_unlock();
    }
    #[inline]
    pub unsafe fn write_unlock(&self) {
        debug_assert_eq!(self.num_readers.load(Ordering::Relaxed), 0);
        debug_assert!(*self.write_locked.get());
        *self.write_locked.get() = false;
        self.raw_unlock();
    }
    #[inline]
    pub unsafe fn destroy(&self) {
        let r = libc::pthread_rwlock_destroy(self.inner.get());
        // On DragonFly pthread_rwlock_destroy() returns EINVAL if called on a
        // rwlock that was just initialized with
        // libc::PTHREAD_RWLOCK_INITIALIZER. Once it is used (locked/unlocked)
        // or pthread_rwlock_init() is called, this behaviour no longer occurs.
        if cfg!(target_os = "dragonfly") {
            debug_assert!(r == 0 || r == libc::EINVAL);
        } else {
            debug_assert_eq!(r, 0);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 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.

//! A module for working with borrowed data.

#![stable(feature = "rust1", since = "1.0.0")]

use core::cmp::Ordering;
use core::hash::{Hash, Hasher};
use core::ops::{Add, AddAssign, Deref};

use fmt;
use string::String;

use self::Cow::*;

#[stable(feature = "rust1", since = "1.0.0")]
pub use core::borrow::{Borrow, BorrowMut};

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B>
    where B: ToOwned,
          <B as ToOwned>::Owned: 'a
{
    fn borrow(&self) -> &B {
        &**self
    }
}

/// A generalization of `Clone` to borrowed data.
///
/// Some types make it possible to go from borrowed to owned, usually by
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
/// from any borrow of a given type.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToOwned {
    #[stable(feature = "rust1", since = "1.0.0")]
    type Owned: Borrow<Self>;

    /// Creates owned data from borrowed data, usually by cloning.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let s: &str = "a";
    /// let ss: String = s.to_owned();
    ///
    /// let v: &[i32] = &[1, 2];
    /// let vv: Vec<i32> = v.to_owned();
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn to_owned(&self) -> Self::Owned;

    /// Uses borrowed data to replace owned data, usually by cloning.
    ///
    /// This is borrow-generalized version of `Clone::clone_from`.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// # #![feature(toowned_clone_into)]
    /// let mut s: String = String::new();
    /// "hello".clone_into(&mut s);
    ///
    /// let mut v: Vec<i32> = Vec::new();
    /// [1, 2][..].clone_into(&mut v);
    /// ```
    #[unstable(feature = "toowned_clone_into",
               reason = "recently added",
               issue = "41263")]
    fn clone_into(&self, target: &mut Self::Owned) {
        *target = self.to_owned();
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ToOwned for T
    where T: Clone
{
    type Owned = T;
    fn to_owned(&self) -> T {
        self.clone()
    }

    fn clone_into(&self, target: &mut T) {
        target.clone_from(self);
    }
}

/// A clone-on-write smart pointer.
///
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
/// can enclose and provide immutable access to borrowed data, and clone the
/// data lazily when mutation or ownership is required. The type is designed to
/// work with general borrowed data via the `Borrow` trait.
///
/// `Cow` implements `Deref`, which means that you can call
/// non-mutating methods directly on the data it encloses. If mutation
/// is desired, `to_mut` will obtain a mutable reference to an owned
/// value, cloning if necessary.
///
/// # Examples
///
/// ```
/// use std::borrow::Cow;
///
/// fn abs_all(input: &mut Cow<[i32]>) {
///     for i in 0..input.len() {
///         let v = input[i];
///         if v < 0 {
///             // Clones into a vector if not already owned.
///             input.to_mut()[i] = -v;
///         }
///     }
/// }
///
/// // No clone occurs because `input` doesn't need to be mutated.
/// let slice = [0, 1, 2];
/// let mut input = Cow::from(&slice[..]);
/// abs_all(&mut input);
///
/// // Clone occurs because `input` needs to be mutated.
/// let slice = [-1, 0, 1];
/// let mut input = Cow::from(&slice[..]);
/// abs_all(&mut input);
///
/// // No clone occurs because `input` is already owned.
/// let mut input = Cow::from(vec![-1, 0, 1]);
/// abs_all(&mut input);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Cow<'a, B: ?Sized + 'a>
    where B: ToOwned
{
    /// Borrowed data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Borrowed(#[stable(feature = "rust1", since = "1.0.0")]
             &'a B),

    /// Owned data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Owned(#[stable(feature = "rust1", since = "1.0.0")]
          <B as ToOwned>::Owned),
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Clone for Cow<'a, B>
    where B: ToOwned
{
    fn clone(&self) -> Cow<'a, B> {
        match *self {
            Borrowed(b) => Borrowed(b),
            Owned(ref o) => {
                let b: &B = o.borrow();
                Owned(b.to_owned())
            }
        }
    }

    fn clone_from(&mut self, source: &Cow<'a, B>) {
        if let Owned(ref mut dest) = *self {
            if let Owned(ref o) = *source {
                o.borrow().clone_into(dest);
                return;
            }
        }

        *self = source.clone();
    }
}

impl<'a, B: ?Sized> Cow<'a, B>
    where B: ToOwned
{
    /// Acquires a mutable reference to the owned form of the data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.to_mut();
    ///
    /// assert_eq!(hello, &[1, 2, 3]);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
        match *self {
            Borrowed(borrowed) => {
                *self = Owned(borrowed.to_owned());
                match *self {
                    Borrowed(..) => unreachable!(),
                    Owned(ref mut owned) => owned,
                }
            }
            Owned(ref mut owned) => owned,
        }
    }

    /// Extracts the owned data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.into_owned();
    ///
    /// assert_eq!(vec![1, 2, 3], hello);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_owned(self) -> <B as ToOwned>::Owned {
        match self {
            Borrowed(borrowed) => borrowed.to_owned(),
            Owned(owned) => owned,
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Deref for Cow<'a, B>
    where B: ToOwned
{
    type Target = B;

    fn deref(&self) -> &B {
        match *self {
            Borrowed(borrowed) => borrowed,
            Owned(ref owned) => owned.borrow(),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Ord for Cow<'a, B>
    where B: Ord + ToOwned
{
    #[inline]
    fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B>
    where B: PartialEq<C> + ToOwned,
          C: ToOwned
{
    #[inline]
    fn eq(&self, other: &Cow<'b, C>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B>
    where B: PartialOrd + ToOwned
{
    #[inline]
    fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B>
    where B: fmt::Debug + ToOwned,
          <B as ToOwned>::Owned: fmt::Debug
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Debug::fmt(b, f),
            Owned(ref o) => fmt::Debug::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Display for Cow<'a, B>
    where B: fmt::Display + ToOwned,
          <B as ToOwned>::Owned: fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Display::fmt(b, f),
            Owned(ref o) => fmt::Display::fmt(o, f),
        }
    }
}

#[stable(feature = "default", since = "1.11.0")]
impl<'a, B: ?Sized> Default for Cow<'a, B>
    where B: ToOwned,
          <B as ToOwned>::Owned: Default
{
    /// Creates an owned Cow<'a, B> with the default value for the contained owned value.
    fn default() -> Cow<'a, B> {
        Owned(<B as ToOwned>::Owned::default())
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Hash for Cow<'a, B>
    where B: Hash + ToOwned
{
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl<'a, T: ?Sized + ToOwned> AsRef<T> for Cow<'a, T> {
    fn as_ref(&self) -> &T {
        self
    }
}

#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> Add<&'a str> for Cow<'a, str> {
    type Output = Cow<'a, str>;

    #[inline]
    fn add(mut self, rhs: &'a str) -> Self::Output {
        self += rhs;
        self
    }
}

#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> Add<Cow<'a, str>> for Cow<'a, str> {
    type Output = Cow<'a, str>;

    #[inline]
    fn add(mut self, rhs: Cow<'a, str>) -> Self::Output {
        self += rhs;
        self
    }
}

#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> AddAssign<&'a str> for Cow<'a, str> {
    fn add_assign(&mut self, rhs: &'a str) {
        if self.is_empty() {
            *self = Cow::Borrowed(rhs)
        } else if rhs.is_empty() {
            return;
        } else {
            if let Cow::Borrowed(lhs) = *self {
                let mut s = String::with_capacity(lhs.len() + rhs.len());
                s.push_str(lhs);
                *self = Cow::Owned(s);
            }
            self.to_mut().push_str(rhs);
        }
    }
}

#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> AddAssign<Cow<'a, str>> for Cow<'a, str> {
    fn add_assign(&mut self, rhs: Cow<'a, str>) {
        if self.is_empty() {
            *self = rhs
        } else if rhs.is_empty() {
            return;
        } else {
            if let Cow::Borrowed(lhs) = *self {
                let mut s = String::with_capacity(lhs.len() + rhs.len());
                s.push_str(lhs);
                *self = Cow::Owned(s);
            }
            self.to_mut().push_str(&rhs);
        }
    }
}
<commit_msg>Auto merge of #42414 - frewsxcv:frewsxcv/improve-cow-docs, r=QuietMisdreavus<commit_after>// Copyright 2014 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.

//! A module for working with borrowed data.

#![stable(feature = "rust1", since = "1.0.0")]

use core::cmp::Ordering;
use core::hash::{Hash, Hasher};
use core::ops::{Add, AddAssign, Deref};

use fmt;
use string::String;

use self::Cow::*;

#[stable(feature = "rust1", since = "1.0.0")]
pub use core::borrow::{Borrow, BorrowMut};

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B>
    where B: ToOwned,
          <B as ToOwned>::Owned: 'a
{
    fn borrow(&self) -> &B {
        &**self
    }
}

/// A generalization of `Clone` to borrowed data.
///
/// Some types make it possible to go from borrowed to owned, usually by
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
/// from any borrow of a given type.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToOwned {
    #[stable(feature = "rust1", since = "1.0.0")]
    type Owned: Borrow<Self>;

    /// Creates owned data from borrowed data, usually by cloning.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let s: &str = "a";
    /// let ss: String = s.to_owned();
    ///
    /// let v: &[i32] = &[1, 2];
    /// let vv: Vec<i32> = v.to_owned();
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn to_owned(&self) -> Self::Owned;

    /// Uses borrowed data to replace owned data, usually by cloning.
    ///
    /// This is borrow-generalized version of `Clone::clone_from`.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// # #![feature(toowned_clone_into)]
    /// let mut s: String = String::new();
    /// "hello".clone_into(&mut s);
    ///
    /// let mut v: Vec<i32> = Vec::new();
    /// [1, 2][..].clone_into(&mut v);
    /// ```
    #[unstable(feature = "toowned_clone_into",
               reason = "recently added",
               issue = "41263")]
    fn clone_into(&self, target: &mut Self::Owned) {
        *target = self.to_owned();
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ToOwned for T
    where T: Clone
{
    type Owned = T;
    fn to_owned(&self) -> T {
        self.clone()
    }

    fn clone_into(&self, target: &mut T) {
        target.clone_from(self);
    }
}

/// A clone-on-write smart pointer.
///
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
/// can enclose and provide immutable access to borrowed data, and clone the
/// data lazily when mutation or ownership is required. The type is designed to
/// work with general borrowed data via the `Borrow` trait.
///
/// `Cow` implements `Deref`, which means that you can call
/// non-mutating methods directly on the data it encloses. If mutation
/// is desired, `to_mut` will obtain a mutable reference to an owned
/// value, cloning if necessary.
///
/// # Examples
///
/// ```
/// use std::borrow::Cow;
///
/// fn abs_all(input: &mut Cow<[i32]>) {
///     for i in 0..input.len() {
///         let v = input[i];
///         if v < 0 {
///             // Clones into a vector if not already owned.
///             input.to_mut()[i] = -v;
///         }
///     }
/// }
///
/// // No clone occurs because `input` doesn't need to be mutated.
/// let slice = [0, 1, 2];
/// let mut input = Cow::from(&slice[..]);
/// abs_all(&mut input);
///
/// // Clone occurs because `input` needs to be mutated.
/// let slice = [-1, 0, 1];
/// let mut input = Cow::from(&slice[..]);
/// abs_all(&mut input);
///
/// // No clone occurs because `input` is already owned.
/// let mut input = Cow::from(vec![-1, 0, 1]);
/// abs_all(&mut input);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Cow<'a, B: ?Sized + 'a>
    where B: ToOwned
{
    /// Borrowed data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Borrowed(#[stable(feature = "rust1", since = "1.0.0")]
             &'a B),

    /// Owned data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Owned(#[stable(feature = "rust1", since = "1.0.0")]
          <B as ToOwned>::Owned),
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Clone for Cow<'a, B>
    where B: ToOwned
{
    fn clone(&self) -> Cow<'a, B> {
        match *self {
            Borrowed(b) => Borrowed(b),
            Owned(ref o) => {
                let b: &B = o.borrow();
                Owned(b.to_owned())
            }
        }
    }

    fn clone_from(&mut self, source: &Cow<'a, B>) {
        if let Owned(ref mut dest) = *self {
            if let Owned(ref o) = *source {
                o.borrow().clone_into(dest);
                return;
            }
        }

        *self = source.clone();
    }
}

impl<'a, B: ?Sized> Cow<'a, B>
    where B: ToOwned
{
    /// Acquires a mutable reference to the owned form of the data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::ascii::AsciiExt;
    /// use std::borrow::Cow;
    ///
    /// let mut cow = Cow::Borrowed("foo");
    /// cow.to_mut().make_ascii_uppercase();
    ///
    /// assert_eq!(
    ///   cow,
    ///   Cow::Owned(String::from("FOO")) as Cow<str>
    /// );
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
        match *self {
            Borrowed(borrowed) => {
                *self = Owned(borrowed.to_owned());
                match *self {
                    Borrowed(..) => unreachable!(),
                    Owned(ref mut owned) => owned,
                }
            }
            Owned(ref mut owned) => owned,
        }
    }

    /// Extracts the owned data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// Calling `into_owned` on a `Cow::Borrowed` clones the underlying data
    /// and becomes a `Cow::Owned`:
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let s = "Hello world!";
    /// let cow = Cow::Borrowed(s);
    ///
    /// assert_eq!(
    ///   cow.into_owned(),
    ///   Cow::Owned(String::from(s))
    /// );
    /// ```
    ///
    /// Calling `into_owned` on a `Cow::Owned` is a no-op:
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let s = "Hello world!";
    /// let cow: Cow<str> = Cow::Owned(String::from(s));
    ///
    /// assert_eq!(
    ///   cow.into_owned(),
    ///   Cow::Owned(String::from(s))
    /// );
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_owned(self) -> <B as ToOwned>::Owned {
        match self {
            Borrowed(borrowed) => borrowed.to_owned(),
            Owned(owned) => owned,
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Deref for Cow<'a, B>
    where B: ToOwned
{
    type Target = B;

    fn deref(&self) -> &B {
        match *self {
            Borrowed(borrowed) => borrowed,
            Owned(ref owned) => owned.borrow(),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Ord for Cow<'a, B>
    where B: Ord + ToOwned
{
    #[inline]
    fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B>
    where B: PartialEq<C> + ToOwned,
          C: ToOwned
{
    #[inline]
    fn eq(&self, other: &Cow<'b, C>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B>
    where B: PartialOrd + ToOwned
{
    #[inline]
    fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B>
    where B: fmt::Debug + ToOwned,
          <B as ToOwned>::Owned: fmt::Debug
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Debug::fmt(b, f),
            Owned(ref o) => fmt::Debug::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Display for Cow<'a, B>
    where B: fmt::Display + ToOwned,
          <B as ToOwned>::Owned: fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Display::fmt(b, f),
            Owned(ref o) => fmt::Display::fmt(o, f),
        }
    }
}

#[stable(feature = "default", since = "1.11.0")]
impl<'a, B: ?Sized> Default for Cow<'a, B>
    where B: ToOwned,
          <B as ToOwned>::Owned: Default
{
    /// Creates an owned Cow<'a, B> with the default value for the contained owned value.
    fn default() -> Cow<'a, B> {
        Owned(<B as ToOwned>::Owned::default())
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Hash for Cow<'a, B>
    where B: Hash + ToOwned
{
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl<'a, T: ?Sized + ToOwned> AsRef<T> for Cow<'a, T> {
    fn as_ref(&self) -> &T {
        self
    }
}

#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> Add<&'a str> for Cow<'a, str> {
    type Output = Cow<'a, str>;

    #[inline]
    fn add(mut self, rhs: &'a str) -> Self::Output {
        self += rhs;
        self
    }
}

#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> Add<Cow<'a, str>> for Cow<'a, str> {
    type Output = Cow<'a, str>;

    #[inline]
    fn add(mut self, rhs: Cow<'a, str>) -> Self::Output {
        self += rhs;
        self
    }
}

#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> AddAssign<&'a str> for Cow<'a, str> {
    fn add_assign(&mut self, rhs: &'a str) {
        if self.is_empty() {
            *self = Cow::Borrowed(rhs)
        } else if rhs.is_empty() {
            return;
        } else {
            if let Cow::Borrowed(lhs) = *self {
                let mut s = String::with_capacity(lhs.len() + rhs.len());
                s.push_str(lhs);
                *self = Cow::Owned(s);
            }
            self.to_mut().push_str(rhs);
        }
    }
}

#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> AddAssign<Cow<'a, str>> for Cow<'a, str> {
    fn add_assign(&mut self, rhs: Cow<'a, str>) {
        if self.is_empty() {
            *self = rhs
        } else if rhs.is_empty() {
            return;
        } else {
            if let Cow::Borrowed(lhs) = *self {
                let mut s = String::with_capacity(lhs.len() + rhs.len());
                s.push_str(lhs);
                *self = Cow::Owned(s);
            }
            self.to_mut().push_str(&rhs);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2014 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.
use self::Context::*;

use rustc::session::Session;

use rustc::hir::map::Map;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir;
use syntax::ast;
use syntax_pos::Span;

#[derive(Clone, Copy, PartialEq)]
enum LoopKind {
    Loop(hir::LoopSource),
    WhileLoop,
    Block,
}

impl LoopKind {
    fn name(self) -> &'static str {
        match self {
            LoopKind::Loop(hir::LoopSource::Loop) => "loop",
            LoopKind::Loop(hir::LoopSource::WhileLet) => "while let",
            LoopKind::Loop(hir::LoopSource::ForLoop) => "for",
            LoopKind::WhileLoop => "while",
            LoopKind::Block => "block",
        }
    }
}

#[derive(Clone, Copy, PartialEq)]
enum Context {
    Normal,
    Loop(LoopKind),
    Closure,
    LabeledBlock,
}

#[derive(Copy, Clone)]
struct CheckLoopVisitor<'a, 'hir: 'a> {
    sess: &'a Session,
    hir_map: &'a Map<'hir>,
    cx: Context,
}

pub fn check_crate(sess: &Session, map: &Map) {
    let krate = map.krate();
    krate.visit_all_item_likes(&mut CheckLoopVisitor {
        sess,
        hir_map: map,
        cx: Normal,
    }.as_deep_visitor());
}

impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
        NestedVisitorMap::OnlyBodies(&self.hir_map)
    }

    fn visit_item(&mut self, i: &'hir hir::Item) {
        self.with_context(Normal, |v| intravisit::walk_item(v, i));
    }

    fn visit_impl_item(&mut self, i: &'hir hir::ImplItem) {
        self.with_context(Normal, |v| intravisit::walk_impl_item(v, i));
    }

    fn visit_expr(&mut self, e: &'hir hir::Expr) {
        match e.node {
            hir::ExprWhile(ref e, ref b, _) => {
                self.with_context(Loop(LoopKind::WhileLoop), |v| {
                    v.visit_expr(&e);
                    v.visit_block(&b);
                });
            }
            hir::ExprLoop(ref b, _, source) => {
                self.with_context(Loop(LoopKind::Loop(source)), |v| v.visit_block(&b));
            }
            hir::ExprClosure(.., b, _, _) => {
                self.with_context(Closure, |v| v.visit_nested_body(b));
            }
            hir::ExprBlock(ref b, Some(_label)) => {
                self.with_context(LabeledBlock, |v| v.visit_block(&b));
            }
            hir::ExprBreak(label, ref opt_expr) => {
                let loop_id = match label.target_id.into() {
                    Ok(loop_id) => loop_id,
                    Err(hir::LoopIdError::OutsideLoopScope) => ast::DUMMY_NODE_ID,
                    Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
                        self.emit_unlabled_cf_in_while_condition(e.span, "break");
                        ast::DUMMY_NODE_ID
                    },
                    Err(hir::LoopIdError::UnresolvedLabel) => ast::DUMMY_NODE_ID,
                };

                if loop_id != ast::DUMMY_NODE_ID {
                    match self.hir_map.find(loop_id).unwrap() {
                        hir::map::NodeBlock(_) => return,
                        _=> (),
                    }
                }

                if self.cx == LabeledBlock {
                    if label.label.is_none() {
                        struct_span_err!(self.sess, e.span, E0695,
                                        "unlabeled `break` inside of a labeled block")
                            .span_label(e.span,
                                        "`break` statements that would diverge to or through \
                                        a labeled block need to bear a label")
                            .emit();
                    }
                    return;
                }

                if opt_expr.is_some() {
                    let loop_kind = if loop_id == ast::DUMMY_NODE_ID {
                        None
                    } else {
                        Some(match self.hir_map.expect_expr(loop_id).node {
                            hir::ExprWhile(..) => LoopKind::WhileLoop,
                            hir::ExprLoop(_, _, source) => LoopKind::Loop(source),
                            hir::ExprBlock(..) => LoopKind::Block,
                            ref r => span_bug!(e.span,
                                               "break label resolved to a non-loop: {:?}", r),
                        })
                    };
                    match loop_kind {
                        None |
                        Some(LoopKind::Loop(hir::LoopSource::Loop)) |
                        Some(LoopKind::Block) => (),
                        Some(kind) => {
                            struct_span_err!(self.sess, e.span, E0571,
                                             "`break` with value from a `{}` loop",
                                             kind.name())
                                .span_label(e.span,
                                            "can only break with a value inside \
                                            `loop` or breakable block")
                                .span_suggestion(e.span,
                                                 &format!("instead, use `break` on its own \
                                                           without a value inside this `{}` loop",
                                                          kind.name()),
                                                 "break".to_string())
                                .emit();
                        }
                    }
                }

                self.require_break_cx("break", e.span);
            }
            hir::ExprAgain(label) => {
                if let Err(hir::LoopIdError::UnlabeledCfInWhileCondition) = label.target_id {
                    self.emit_unlabled_cf_in_while_condition(e.span, "continue");
                }
                self.require_break_cx("continue", e.span)
            },
            _ => intravisit::walk_expr(self, e),
        }
    }
}

impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
    fn with_context<F>(&mut self, cx: Context, f: F)
        where F: FnOnce(&mut CheckLoopVisitor<'a, 'hir>)
    {
        let old_cx = self.cx;
        self.cx = cx;
        f(self);
        self.cx = old_cx;
    }

    fn require_break_cx(&self, name: &str, span: Span) {
        match self.cx {
            LabeledBlock |
            Loop(_) => {}
            Closure => {
                struct_span_err!(self.sess, span, E0267, "`{}` inside of a closure", name)
                .span_label(span, "cannot break inside of a closure")
                .emit();
            }
            Normal => {
                struct_span_err!(self.sess, span, E0268, "`{}` outside of loop", name)
                .span_label(span, "cannot break outside of a loop")
                .emit();
            }
        }
    }

    fn emit_unlabled_cf_in_while_condition(&mut self, span: Span, cf_type: &str) {
        struct_span_err!(self.sess, span, E0590,
                         "`break` or `continue` with no label in the condition of a `while` loop")
            .span_label(span,
                        format!("unlabeled `{}` in the condition of a `while` loop", cf_type))
            .emit();
    }
}
<commit_msg>Extend error E0695 to unlabeled continue statements<commit_after>// Copyright 2012-2014 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.
use self::Context::*;

use rustc::session::Session;

use rustc::hir::map::Map;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::{self, Destination};
use syntax::ast;
use syntax_pos::Span;

#[derive(Clone, Copy, PartialEq)]
enum LoopKind {
    Loop(hir::LoopSource),
    WhileLoop,
    Block,
}

impl LoopKind {
    fn name(self) -> &'static str {
        match self {
            LoopKind::Loop(hir::LoopSource::Loop) => "loop",
            LoopKind::Loop(hir::LoopSource::WhileLet) => "while let",
            LoopKind::Loop(hir::LoopSource::ForLoop) => "for",
            LoopKind::WhileLoop => "while",
            LoopKind::Block => "block",
        }
    }
}

#[derive(Clone, Copy, PartialEq)]
enum Context {
    Normal,
    Loop(LoopKind),
    Closure,
    LabeledBlock,
}

#[derive(Copy, Clone)]
struct CheckLoopVisitor<'a, 'hir: 'a> {
    sess: &'a Session,
    hir_map: &'a Map<'hir>,
    cx: Context,
}

pub fn check_crate(sess: &Session, map: &Map) {
    let krate = map.krate();
    krate.visit_all_item_likes(&mut CheckLoopVisitor {
        sess,
        hir_map: map,
        cx: Normal,
    }.as_deep_visitor());
}

impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
        NestedVisitorMap::OnlyBodies(&self.hir_map)
    }

    fn visit_item(&mut self, i: &'hir hir::Item) {
        self.with_context(Normal, |v| intravisit::walk_item(v, i));
    }

    fn visit_impl_item(&mut self, i: &'hir hir::ImplItem) {
        self.with_context(Normal, |v| intravisit::walk_impl_item(v, i));
    }

    fn visit_expr(&mut self, e: &'hir hir::Expr) {
        match e.node {
            hir::ExprWhile(ref e, ref b, _) => {
                self.with_context(Loop(LoopKind::WhileLoop), |v| {
                    v.visit_expr(&e);
                    v.visit_block(&b);
                });
            }
            hir::ExprLoop(ref b, _, source) => {
                self.with_context(Loop(LoopKind::Loop(source)), |v| v.visit_block(&b));
            }
            hir::ExprClosure(.., b, _, _) => {
                self.with_context(Closure, |v| v.visit_nested_body(b));
            }
            hir::ExprBlock(ref b, Some(_label)) => {
                self.with_context(LabeledBlock, |v| v.visit_block(&b));
            }
            hir::ExprBreak(label, ref opt_expr) => {
                self.require_label_in_labeled_block(e.span, &label, "break");

                let loop_id = match label.target_id.into() {
                    Ok(loop_id) => loop_id,
                    Err(hir::LoopIdError::OutsideLoopScope) => ast::DUMMY_NODE_ID,
                    Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
                        self.emit_unlabled_cf_in_while_condition(e.span, "break");
                        ast::DUMMY_NODE_ID
                    },
                    Err(hir::LoopIdError::UnresolvedLabel) => ast::DUMMY_NODE_ID,
                };

                if loop_id != ast::DUMMY_NODE_ID {
                    match self.hir_map.find(loop_id).unwrap() {
                        hir::map::NodeBlock(_) => return,
                        _=> (),
                    }
                }

                if self.cx == LabeledBlock {
                    return;
                }

                if opt_expr.is_some() {
                    let loop_kind = if loop_id == ast::DUMMY_NODE_ID {
                        None
                    } else {
                        Some(match self.hir_map.expect_expr(loop_id).node {
                            hir::ExprWhile(..) => LoopKind::WhileLoop,
                            hir::ExprLoop(_, _, source) => LoopKind::Loop(source),
                            hir::ExprBlock(..) => LoopKind::Block,
                            ref r => span_bug!(e.span,
                                               "break label resolved to a non-loop: {:?}", r),
                        })
                    };
                    match loop_kind {
                        None |
                        Some(LoopKind::Loop(hir::LoopSource::Loop)) |
                        Some(LoopKind::Block) => (),
                        Some(kind) => {
                            struct_span_err!(self.sess, e.span, E0571,
                                             "`break` with value from a `{}` loop",
                                             kind.name())
                                .span_label(e.span,
                                            "can only break with a value inside \
                                            `loop` or breakable block")
                                .span_suggestion(e.span,
                                                 &format!("instead, use `break` on its own \
                                                           without a value inside this `{}` loop",
                                                          kind.name()),
                                                 "break".to_string())
                                .emit();
                        }
                    }
                }

                self.require_break_cx("break", e.span);
            }
            hir::ExprAgain(label) => {
                self.require_label_in_labeled_block(e.span, &label, "continue");

                if let Err(hir::LoopIdError::UnlabeledCfInWhileCondition) = label.target_id {
                    self.emit_unlabled_cf_in_while_condition(e.span, "continue");
                }
                self.require_break_cx("continue", e.span)
            },
            _ => intravisit::walk_expr(self, e),
        }
    }
}

impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
    fn with_context<F>(&mut self, cx: Context, f: F)
        where F: FnOnce(&mut CheckLoopVisitor<'a, 'hir>)
    {
        let old_cx = self.cx;
        self.cx = cx;
        f(self);
        self.cx = old_cx;
    }

    fn require_break_cx(&self, name: &str, span: Span) {
        match self.cx {
            LabeledBlock |
            Loop(_) => {}
            Closure => {
                struct_span_err!(self.sess, span, E0267, "`{}` inside of a closure", name)
                .span_label(span, "cannot break inside of a closure")
                .emit();
            }
            Normal => {
                struct_span_err!(self.sess, span, E0268, "`{}` outside of loop", name)
                .span_label(span, "cannot break outside of a loop")
                .emit();
            }
        }
    }

    fn require_label_in_labeled_block(&mut self, span: Span, label: &Destination, cf_type: &str) {
        if self.cx == LabeledBlock {
            if label.label.is_none() {
                struct_span_err!(self.sess, span, E0695,
                                "unlabeled `{}` inside of a labeled block", cf_type)
                    .span_label(span,
                                format!("`{}` statements that would diverge to or through \
                                a labeled block need to bear a label", cf_type))
                    .emit();
            }
        }
    }
    fn emit_unlabled_cf_in_while_condition(&mut self, span: Span, cf_type: &str) {
        struct_span_err!(self.sess, span, E0590,
                         "`break` or `continue` with no label in the condition of a `while` loop")
            .span_label(span,
                        format!("unlabeled `{}` in the condition of a `while` loop", cf_type))
            .emit();
    }
}
<|endoftext|>