<commit_before>use rustc::ty::Ty;
use rustc::ty::layout::LayoutOf;
use syntax::ast::{FloatTy, IntTy, UintTy};

use rustc_apfloat::ieee::{Single, Double};
use super::{EvalContext, Machine};
use rustc::mir::interpret::{Scalar, EvalResult, Pointer, PointerArithmetic};
use rustc_apfloat::Float;

impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
    pub(super) fn cast_primval(
        &self,
        val: Scalar,
        src_ty: Ty<'tcx>,
        dest_ty: Ty<'tcx>,
    ) -> EvalResult<'tcx, Scalar> {
        use rustc::ty::TypeVariants::*;
        trace!("Casting {:?}: {:?} to {:?}", val, src_ty, dest_ty);

        match val {
            Scalar::Bits { defined: 0, .. } => Ok(val),
            Scalar::Ptr(ptr) => self.cast_from_ptr(ptr, dest_ty),
            Scalar::Bits { bits, .. } => {
                // TODO(oli-obk): impl scalar_size for floats and check defined bits here
                match src_ty.sty {
                    TyFloat(fty) => self.cast_from_float(bits, fty, dest_ty),
                    _ => self.cast_from_int(bits, src_ty, dest_ty),
                }
            }
        }
    }

    fn cast_from_int(
        &self,
        v: u128,
        src_ty: Ty<'tcx>,
        dest_ty: Ty<'tcx>,
    ) -> EvalResult<'tcx, Scalar> {
        let signed = self.layout_of(src_ty)?.abi.is_signed();
        let v = if signed {
            self.sign_extend(v, src_ty)?
        } else {
            v
        };
        trace!("cast_from_int: {}, {}, {}", v, src_ty, dest_ty);
        use rustc::ty::TypeVariants::*;
        match dest_ty.sty {
            TyInt(_) | TyUint(_) => {
                let v = self.truncate(v, dest_ty)?;
                Ok(Scalar::Bits {
                    bits: v,
                    defined: dest_ty.scalar_size(self.tcx.tcx).unwrap().bits() as u8,
                })
            }

            TyFloat(FloatTy::F32) if signed => Ok(Scalar::Bits {
                bits: Single::from_i128(v as i128).value.to_bits(),
                defined: 32,
            }),
            TyFloat(FloatTy::F64) if signed => Ok(Scalar::Bits {
                bits: Double::from_i128(v as i128).value.to_bits(),
                defined: 64,
            }),
            TyFloat(FloatTy::F32) => Ok(Scalar::Bits {
                bits: Single::from_u128(v).value.to_bits(),
                defined: 32,
            }),
            TyFloat(FloatTy::F64) => Ok(Scalar::Bits {
                bits: Double::from_u128(v).value.to_bits(),
                defined: 64,
            }),

            TyChar if v as u8 as u128 == v => Ok(Scalar::Bits { bits: v, defined: 32 }),
            TyChar => err!(InvalidChar(v)),

            // No alignment check needed for raw pointers.  But we have to truncate to target ptr size.
            TyRawPtr(_) => {
                Ok(Scalar::Bits {
                    bits: self.memory.truncate_to_ptr(v).0 as u128,
                    defined: self.memory.pointer_size().bits() as u8,
                })
            },

            // Casts to bool are not permitted by rustc, no need to handle them here.
            _ => err!(Unimplemented(format!("int to {:?} cast", dest_ty))),
        }
    }

    fn cast_from_float(&self, bits: u128, fty: FloatTy, dest_ty: Ty<'tcx>) -> EvalResult<'tcx, Scalar> {
        use rustc::ty::TypeVariants::*;
        use rustc_apfloat::FloatConvert;
        match dest_ty.sty {
            // float -> uint
            TyUint(t) => {
                let width = t.bit_width().unwrap_or(self.memory.pointer_size().bytes() as usize * 8);
                match fty {
                    FloatTy::F32 => Ok(Scalar::Bits {
                        bits: Single::from_bits(bits).to_u128(width).value,
                        defined: 32,
                    }),
                    FloatTy::F64 => Ok(Scalar::Bits {
                        bits: Double::from_bits(bits).to_u128(width).value,
                        defined: 64,
                    }),
                }
            },
            // float -> int
            TyInt(t) => {
                let width = t.bit_width().unwrap_or(self.memory.pointer_size().bytes() as usize * 8);
                match fty {
                    FloatTy::F32 => Ok(Scalar::Bits {
                        bits: Single::from_bits(bits).to_i128(width).value as u128,
                        defined: 32,
                    }),
                    FloatTy::F64 => Ok(Scalar::Bits {
                        bits: Double::from_bits(bits).to_i128(width).value as u128,
                        defined: 64,
                    }),
                }
            },
            // f64 -> f32
            TyFloat(FloatTy::F32) if fty == FloatTy::F64 => {
                Ok(Scalar::Bits {
                    bits: Single::to_bits(Double::from_bits(bits).convert(&mut false).value),
                    defined: 32,
                })
            },
            // f32 -> f64
            TyFloat(FloatTy::F64) if fty == FloatTy::F32 => {
                Ok(Scalar::Bits {
                    bits: Double::to_bits(Single::from_bits(bits).convert(&mut false).value),
                    defined: 64,
                })
            },
            // identity cast
            TyFloat(FloatTy:: F64) => Ok(Scalar::Bits {
                bits,
                defined: 64,
            }),
            TyFloat(FloatTy:: F32) => Ok(Scalar::Bits {
                bits,
                defined: 32,
            }),
            _ => err!(Unimplemented(format!("float to {:?} cast", dest_ty))),
        }
    }

    fn cast_from_ptr(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Scalar> {
        use rustc::ty::TypeVariants::*;
        match ty.sty {
            // Casting to a reference or fn pointer is not permitted by rustc, no need to support it here.
            TyRawPtr(_) |
            TyInt(IntTy::Isize) |
            TyUint(UintTy::Usize) => Ok(ptr.into()),
            TyInt(_) | TyUint(_) => err!(ReadPointerAsBytes),
            _ => err!(Unimplemented(format!("ptr to {:?} cast", ty))),
        }
    }
}
<commit_msg>Use the target types bitsize instead of the source type's<commit_after>use rustc::ty::Ty;
use rustc::ty::layout::LayoutOf;
use syntax::ast::{FloatTy, IntTy, UintTy};

use rustc_apfloat::ieee::{Single, Double};
use super::{EvalContext, Machine};
use rustc::mir::interpret::{Scalar, EvalResult, Pointer, PointerArithmetic};
use rustc_apfloat::Float;

impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
    pub(super) fn cast_primval(
        &self,
        val: Scalar,
        src_ty: Ty<'tcx>,
        dest_ty: Ty<'tcx>,
    ) -> EvalResult<'tcx, Scalar> {
        use rustc::ty::TypeVariants::*;
        trace!("Casting {:?}: {:?} to {:?}", val, src_ty, dest_ty);

        match val {
            Scalar::Bits { defined: 0, .. } => Ok(val),
            Scalar::Ptr(ptr) => self.cast_from_ptr(ptr, dest_ty),
            Scalar::Bits { bits, .. } => {
                // TODO(oli-obk): impl scalar_size for floats and check defined bits here
                match src_ty.sty {
                    TyFloat(fty) => self.cast_from_float(bits, fty, dest_ty),
                    _ => self.cast_from_int(bits, src_ty, dest_ty),
                }
            }
        }
    }

    fn cast_from_int(
        &self,
        v: u128,
        src_ty: Ty<'tcx>,
        dest_ty: Ty<'tcx>,
    ) -> EvalResult<'tcx, Scalar> {
        let signed = self.layout_of(src_ty)?.abi.is_signed();
        let v = if signed {
            self.sign_extend(v, src_ty)?
        } else {
            v
        };
        trace!("cast_from_int: {}, {}, {}", v, src_ty, dest_ty);
        use rustc::ty::TypeVariants::*;
        match dest_ty.sty {
            TyInt(_) | TyUint(_) => {
                let v = self.truncate(v, dest_ty)?;
                Ok(Scalar::Bits {
                    bits: v,
                    defined: dest_ty.scalar_size(self.tcx.tcx).unwrap().bits() as u8,
                })
            }

            TyFloat(FloatTy::F32) if signed => Ok(Scalar::Bits {
                bits: Single::from_i128(v as i128).value.to_bits(),
                defined: 32,
            }),
            TyFloat(FloatTy::F64) if signed => Ok(Scalar::Bits {
                bits: Double::from_i128(v as i128).value.to_bits(),
                defined: 64,
            }),
            TyFloat(FloatTy::F32) => Ok(Scalar::Bits {
                bits: Single::from_u128(v).value.to_bits(),
                defined: 32,
            }),
            TyFloat(FloatTy::F64) => Ok(Scalar::Bits {
                bits: Double::from_u128(v).value.to_bits(),
                defined: 64,
            }),

            TyChar if v as u8 as u128 == v => Ok(Scalar::Bits { bits: v, defined: 32 }),
            TyChar => err!(InvalidChar(v)),

            // No alignment check needed for raw pointers.  But we have to truncate to target ptr size.
            TyRawPtr(_) => {
                Ok(Scalar::Bits {
                    bits: self.memory.truncate_to_ptr(v).0 as u128,
                    defined: self.memory.pointer_size().bits() as u8,
                })
            },

            // Casts to bool are not permitted by rustc, no need to handle them here.
            _ => err!(Unimplemented(format!("int to {:?} cast", dest_ty))),
        }
    }

    fn cast_from_float(&self, bits: u128, fty: FloatTy, dest_ty: Ty<'tcx>) -> EvalResult<'tcx, Scalar> {
        use rustc::ty::TypeVariants::*;
        use rustc_apfloat::FloatConvert;
        match dest_ty.sty {
            // float -> uint
            TyUint(t) => {
                let width = t.bit_width().unwrap_or(self.memory.pointer_size().bits() as usize);
                match fty {
                    FloatTy::F32 => Ok(Scalar::Bits {
                        bits: Single::from_bits(bits).to_u128(width).value,
                        defined: width as u8,
                    }),
                    FloatTy::F64 => Ok(Scalar::Bits {
                        bits: Double::from_bits(bits).to_u128(width).value,
                        defined: width as u8,
                    }),
                }
            },
            // float -> int
            TyInt(t) => {
                let width = t.bit_width().unwrap_or(self.memory.pointer_size().bits() as usize);
                match fty {
                    FloatTy::F32 => Ok(Scalar::Bits {
                        bits: Single::from_bits(bits).to_i128(width).value as u128,
                        defined: width as u8,
                    }),
                    FloatTy::F64 => Ok(Scalar::Bits {
                        bits: Double::from_bits(bits).to_i128(width).value as u128,
                        defined: width as u8,
                    }),
                }
            },
            // f64 -> f32
            TyFloat(FloatTy::F32) if fty == FloatTy::F64 => {
                Ok(Scalar::Bits {
                    bits: Single::to_bits(Double::from_bits(bits).convert(&mut false).value),
                    defined: 32,
                })
            },
            // f32 -> f64
            TyFloat(FloatTy::F64) if fty == FloatTy::F32 => {
                Ok(Scalar::Bits {
                    bits: Double::to_bits(Single::from_bits(bits).convert(&mut false).value),
                    defined: 64,
                })
            },
            // identity cast
            TyFloat(FloatTy:: F64) => Ok(Scalar::Bits {
                bits,
                defined: 64,
            }),
            TyFloat(FloatTy:: F32) => Ok(Scalar::Bits {
                bits,
                defined: 32,
            }),
            _ => err!(Unimplemented(format!("float to {:?} cast", dest_ty))),
        }
    }

    fn cast_from_ptr(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Scalar> {
        use rustc::ty::TypeVariants::*;
        match ty.sty {
            // Casting to a reference or fn pointer is not permitted by rustc, no need to support it here.
            TyRawPtr(_) |
            TyInt(IntTy::Isize) |
            TyUint(UintTy::Usize) => Ok(ptr.into()),
            TyInt(_) | TyUint(_) => err!(ReadPointerAsBytes),
            _ => err!(Unimplemented(format!("ptr to {:?} cast", ty))),
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>[Auto] lib/entry/ref: Fix Clippy warnings<commit_after><|endoftext|>


<commit_before><commit_msg>add a testing<commit_after><|endoftext|>


<commit_before><commit_msg>add clone macro and etc..<commit_after><|endoftext|>


<commit_before><commit_msg>Add regression test for ICE from issue 10846.<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.

// This is a regression test for the ICE from issue #10846.
//
// The original issue causing the ICE: the LUB-computations during
// type inference were encountering late-bound lifetimes, and
// asserting that such lifetimes should have already been subsituted
// with a concrete lifetime.
//
// However, those encounters were occurring within the lexical scope
// of the binding for the late-bound lifetime; that is, the late-bound
// lifetimes were perfectly valid.  The core problem was that the type
// folding code was over-zealously passing back all lifetimes when
// doing region-folding, when really all clients of the region-folding
// case only want to see FREE lifetime variables, not bound ones.

pub fn main() {
    fn explicit() {
        fn test(_x: Option<|f: <'a> |g: &'a int||>) {}
        test(Some(|_f: <'a> |g: &'a int|| {}));
    }

    // The code below is shorthand for the code above (and more likely
    // to represent what one encounters in practice).
    fn implicit() {
        fn test(_x: Option<|f:      |g: &   int||>) {}
        test(Some(|_f:      |g: &   int|| {}));
    }

    explicit();
    implicit();
}
<|endoftext|>


<commit_before><commit_msg>Rollup merge of #40588 - topecongiro:add-missing-tests, r=alexcrichton<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.

#[repr(u8)]
enum Foo {
    Foo(u8),
}

fn main() {
    match Foo::Foo(1) {
        _ => ()
    }
}
<|endoftext|>


<commit_before><commit_msg>src/addressbook.rs: store addressbook entries<commit_after><|endoftext|>


<commit_before>//! Sorting methods
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];

import vec::{len, push};
import core::cmp::{Eq, Ord};

export le;
export merge_sort;
export quick_sort;
export quick_sort3;

type le<T> = pure fn(v1: &T, v2: &T) -> bool;

/**
 * Merge sort. Returns a new vector containing the sorted list.
 *
 * Has worst case O(n log n) performance, best case O(n), but
 * is not space efficient. This is a stable sort.
 */
fn merge_sort<T: copy>(le: le<T>, v: &[const T]) -> ~[T] {
    type slice = (uint, uint);

    return merge_sort_(le, v, (0u, len(v)));

    fn merge_sort_<T: copy>(le: le<T>, v: &[const T], slice: slice)
        -> ~[T] {
        let begin = slice.first();
        let end = slice.second();

        let v_len = end - begin;
        if v_len == 0u { return ~[]; }
        if v_len == 1u { return ~[v[begin]]; }

        let mid = v_len / 2u + begin;
        let a = (begin, mid);
        let b = (mid, end);
        return merge(le, merge_sort_(le, v, a), merge_sort_(le, v, b));
    }

    fn merge<T: copy>(le: le<T>, a: &[T], b: &[T]) -> ~[T] {
        let mut rs = ~[];
        vec::reserve(rs, len(a) + len(b));
        let a_len = len(a);
        let mut a_ix = 0u;
        let b_len = len(b);
        let mut b_ix = 0u;
        while a_ix < a_len && b_ix < b_len {
            if le(&a[a_ix], &b[b_ix]) {
                vec::push(rs, a[a_ix]);
                a_ix += 1u;
            } else { vec::push(rs, b[b_ix]); b_ix += 1u; }
        }
        rs = vec::append(rs, vec::slice(a, a_ix, a_len));
        rs = vec::append(rs, vec::slice(b, b_ix, b_len));
        return rs;
    }
}

fn part<T: copy>(compare_func: le<T>, arr: &[mut T], left: uint,
                right: uint, pivot: uint) -> uint {
    let pivot_value = arr[pivot];
    arr[pivot] <-> arr[right];
    let mut storage_index: uint = left;
    let mut i: uint = left;
    while i < right {
        if compare_func(&arr[i], &pivot_value) {
            arr[i] <-> arr[storage_index];
            storage_index += 1u;
        }
        i += 1u;
    }
    arr[storage_index] <-> arr[right];
    return storage_index;
}

fn qsort<T: copy>(compare_func: le<T>, arr: &[mut T], left: uint,
             right: uint) {
    if right > left {
        let pivot = (left + right) / 2u;
        let new_pivot = part::<T>(compare_func, arr, left, right, pivot);
        if new_pivot != 0u {
            // Need to do this check before recursing due to overflow
            qsort::<T>(compare_func, arr, left, new_pivot - 1u);
        }
        qsort::<T>(compare_func, arr, new_pivot + 1u, right);
    }
}

/**
 * Quicksort. Sorts a mut vector in place.
 *
 * Has worst case O(n^2) performance, average case O(n log n).
 * This is an unstable sort.
 */
fn quick_sort<T: copy>(compare_func: le<T>, arr: &[mut T]) {
    if len::<T>(arr) == 0u { return; }
    qsort::<T>(compare_func, arr, 0u, len::<T>(arr) - 1u);
}

fn qsort3<T: copy Ord Eq>(arr: &[mut T], left: int, right: int) {
    if right <= left { return; }
    let v: T = arr[right];
    let mut i: int = left - 1;
    let mut j: int = right;
    let mut p: int = i;
    let mut q: int = j;
    loop {
        i += 1;
        while arr[i] < v { i += 1; }
        j -= 1;
        while v < arr[j] {
            if j == left { break; }
            j -= 1;
        }
        if i >= j { break; }
        arr[i] <-> arr[j];
        if arr[i] == v {
            p += 1;
            arr[p] <-> arr[i];
        }
        if v == arr[j] {
            q -= 1;
            arr[j] <-> arr[q];
        }
    }
    arr[i] <-> arr[right];
    j = i - 1;
    i += 1;
    let mut k: int = left;
    while k < p {
        arr[k] <-> arr[j];
        k += 1;
        j -= 1;
        if k == len::<T>(arr) as int { break; }
    }
    k = right - 1;
    while k > q {
        arr[i] <-> arr[k];
        k -= 1;
        i += 1;
        if k == 0 { break; }
    }
    qsort3::<T>(arr, left, j);
    qsort3::<T>(arr, i, right);
}

/**
 * Fancy quicksort. Sorts a mut vector in place.
 *
 * Based on algorithm presented by ~[Sedgewick and Bentley]
 * (http://www.cs.princeton.edu/~rs/talks/QuicksortIsOptimal.pdf).
 * According to these slides this is the algorithm of choice for
 * 'randomly ordered keys, abstract compare' & 'small number of key values'.
 *
 * This is an unstable sort.
 */
fn quick_sort3<T: copy Ord Eq>(arr: &[mut T]) {
    if arr.len() <= 1 { return; }
    qsort3(arr, 0, (arr.len() - 1) as int);
}

#[cfg(test)]
mod test_qsort3 {
    fn check_sort(v1: &[mut int], v2: &[mut int]) {
        let len = vec::len::<int>(v1);
        quick_sort3::<int>(v1);
        let mut i = 0u;
        while i < len {
            log(debug, v2[i]);
            assert (v2[i] == v1[i]);
            i += 1u;
        }
    }

    #[test]
    fn test() {
        {
            let v1 = ~[mut 3, 7, 4, 5, 2, 9, 5, 8];
            let v2 = ~[mut 2, 3, 4, 5, 5, 7, 8, 9];
            check_sort(v1, v2);
        }
        {
            let v1 = ~[mut 1, 1, 1];
            let v2 = ~[mut 1, 1, 1];
            check_sort(v1, v2);
        }
        {
            let v1: ~[mut int] = ~[mut];
            let v2: ~[mut int] = ~[mut];
            check_sort(v1, v2);
        }
        { let v1 = ~[mut 9]; let v2 = ~[mut 9]; check_sort(v1, v2); }
        {
            let v1 = ~[mut 9, 3, 3, 3, 9];
            let v2 = ~[mut 3, 3, 3, 9, 9];
            check_sort(v1, v2);
        }
    }
}

#[cfg(test)]
mod test_qsort {
    fn check_sort(v1: &[mut int], v2: &[mut int]) {
        let len = vec::len::<int>(v1);
        pure fn leual(a: &int, b: &int) -> bool { *a <= *b }
        quick_sort::<int>(leual, v1);
        let mut i = 0u;
        while i < len {
            log(debug, v2[i]);
            assert (v2[i] == v1[i]);
            i += 1u;
        }
    }

    #[test]
    fn test() {
        {
            let v1 = ~[mut 3, 7, 4, 5, 2, 9, 5, 8];
            let v2 = ~[mut 2, 3, 4, 5, 5, 7, 8, 9];
            check_sort(v1, v2);
        }
        {
            let v1 = ~[mut 1, 1, 1];
            let v2 = ~[mut 1, 1, 1];
            check_sort(v1, v2);
        }
        {
            let v1: ~[mut int] = ~[mut];
            let v2: ~[mut int] = ~[mut];
            check_sort(v1, v2);
        }
        { let v1 = ~[mut 9]; let v2 = ~[mut 9]; check_sort(v1, v2); }
        {
            let v1 = ~[mut 9, 3, 3, 3, 9];
            let v2 = ~[mut 3, 3, 3, 9, 9];
            check_sort(v1, v2);
        }
    }

    // Regression test for #750
    #[test]
    fn test_simple() {
        let names = ~[mut 2, 1, 3];

        let expected = ~[1, 2, 3];

        sort::quick_sort(|x, y| { int::le(*x, *y) }, names);

        let immut_names = vec::from_mut(names);

        let pairs = vec::zip(expected, immut_names);
        for vec::each(pairs) |p| {
            let (a, b) = p;
            debug!("%d %d", a, b);
            assert (a == b);
        }
    }
}

#[cfg(test)]
mod tests {

    fn check_sort(v1: &[int], v2: &[int]) {
        let len = vec::len::<int>(v1);
        pure fn le(a: &int, b: &int) -> bool { *a <= *b }
        let f = le;
        let v3 = merge_sort::<int>(f, v1);
        let mut i = 0u;
        while i < len {
            log(debug, v3[i]);
            assert (v3[i] == v2[i]);
            i += 1u;
        }
    }

    #[test]
    fn test() {
        {
            let v1 = ~[3, 7, 4, 5, 2, 9, 5, 8];
            let v2 = ~[2, 3, 4, 5, 5, 7, 8, 9];
            check_sort(v1, v2);
        }
        { let v1 = ~[1, 1, 1]; let v2 = ~[1, 1, 1]; check_sort(v1, v2); }
        { let v1:~[int] = ~[]; let v2:~[int] = ~[]; check_sort(v1, v2); }
        { let v1 = ~[9]; let v2 = ~[9]; check_sort(v1, v2); }
        {
            let v1 = ~[9, 3, 3, 3, 9];
            let v2 = ~[3, 3, 3, 9, 9];
            check_sort(v1, v2);
        }
    }

    #[test]
    fn test_merge_sort_mutable() {
        pure fn le(a: &int, b: &int) -> bool { *a <= *b }
        let v1 = ~[mut 3, 2, 1];
        let v2 = merge_sort(le, v1);
        assert v2 == ~[1, 2, 3];
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>libstd: Implement a Sort trait.<commit_after>//! Sorting methods
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];

import vec::{len, push};
import core::cmp::{Eq, Ord};

export le;
export merge_sort;
export quick_sort;
export quick_sort3;
export Sort;

type le<T> = pure fn(v1: &T, v2: &T) -> bool;

/**
 * Merge sort. Returns a new vector containing the sorted list.
 *
 * Has worst case O(n log n) performance, best case O(n), but
 * is not space efficient. This is a stable sort.
 */
fn merge_sort<T: copy>(le: le<T>, v: &[const T]) -> ~[T] {
    type slice = (uint, uint);

    return merge_sort_(le, v, (0u, len(v)));

    fn merge_sort_<T: copy>(le: le<T>, v: &[const T], slice: slice)
        -> ~[T] {
        let begin = slice.first();
        let end = slice.second();

        let v_len = end - begin;
        if v_len == 0u { return ~[]; }
        if v_len == 1u { return ~[v[begin]]; }

        let mid = v_len / 2u + begin;
        let a = (begin, mid);
        let b = (mid, end);
        return merge(le, merge_sort_(le, v, a), merge_sort_(le, v, b));
    }

    fn merge<T: copy>(le: le<T>, a: &[T], b: &[T]) -> ~[T] {
        let mut rs = ~[];
        vec::reserve(rs, len(a) + len(b));
        let a_len = len(a);
        let mut a_ix = 0u;
        let b_len = len(b);
        let mut b_ix = 0u;
        while a_ix < a_len && b_ix < b_len {
            if le(&a[a_ix], &b[b_ix]) {
                vec::push(rs, a[a_ix]);
                a_ix += 1u;
            } else { vec::push(rs, b[b_ix]); b_ix += 1u; }
        }
        rs = vec::append(rs, vec::slice(a, a_ix, a_len));
        rs = vec::append(rs, vec::slice(b, b_ix, b_len));
        return rs;
    }
}

fn part<T: copy>(compare_func: le<T>, arr: &[mut T], left: uint,
                right: uint, pivot: uint) -> uint {
    let pivot_value = arr[pivot];
    arr[pivot] <-> arr[right];
    let mut storage_index: uint = left;
    let mut i: uint = left;
    while i < right {
        if compare_func(&arr[i], &pivot_value) {
            arr[i] <-> arr[storage_index];
            storage_index += 1u;
        }
        i += 1u;
    }
    arr[storage_index] <-> arr[right];
    return storage_index;
}

fn qsort<T: copy>(compare_func: le<T>, arr: &[mut T], left: uint,
             right: uint) {
    if right > left {
        let pivot = (left + right) / 2u;
        let new_pivot = part::<T>(compare_func, arr, left, right, pivot);
        if new_pivot != 0u {
            // Need to do this check before recursing due to overflow
            qsort::<T>(compare_func, arr, left, new_pivot - 1u);
        }
        qsort::<T>(compare_func, arr, new_pivot + 1u, right);
    }
}

/**
 * Quicksort. Sorts a mut vector in place.
 *
 * Has worst case O(n^2) performance, average case O(n log n).
 * This is an unstable sort.
 */
fn quick_sort<T: copy>(compare_func: le<T>, arr: &[mut T]) {
    if len::<T>(arr) == 0u { return; }
    qsort::<T>(compare_func, arr, 0u, len::<T>(arr) - 1u);
}

fn qsort3<T: copy Ord Eq>(arr: &[mut T], left: int, right: int) {
    if right <= left { return; }
    let v: T = arr[right];
    let mut i: int = left - 1;
    let mut j: int = right;
    let mut p: int = i;
    let mut q: int = j;
    loop {
        i += 1;
        while arr[i] < v { i += 1; }
        j -= 1;
        while v < arr[j] {
            if j == left { break; }
            j -= 1;
        }
        if i >= j { break; }
        arr[i] <-> arr[j];
        if arr[i] == v {
            p += 1;
            arr[p] <-> arr[i];
        }
        if v == arr[j] {
            q -= 1;
            arr[j] <-> arr[q];
        }
    }
    arr[i] <-> arr[right];
    j = i - 1;
    i += 1;
    let mut k: int = left;
    while k < p {
        arr[k] <-> arr[j];
        k += 1;
        j -= 1;
        if k == len::<T>(arr) as int { break; }
    }
    k = right - 1;
    while k > q {
        arr[i] <-> arr[k];
        k -= 1;
        i += 1;
        if k == 0 { break; }
    }
    qsort3::<T>(arr, left, j);
    qsort3::<T>(arr, i, right);
}

/**
 * Fancy quicksort. Sorts a mut vector in place.
 *
 * Based on algorithm presented by ~[Sedgewick and Bentley]
 * (http://www.cs.princeton.edu/~rs/talks/QuicksortIsOptimal.pdf).
 * According to these slides this is the algorithm of choice for
 * 'randomly ordered keys, abstract compare' & 'small number of key values'.
 *
 * This is an unstable sort.
 */
fn quick_sort3<T: copy Ord Eq>(arr: &[mut T]) {
    if arr.len() <= 1 { return; }
    qsort3(arr, 0, (arr.len() - 1) as int);
}

trait Sort {
    fn qsort(self);
}

impl<T: copy Ord Eq> &[mut T] : Sort {
    fn qsort(self) { quick_sort3(self); }
}

#[cfg(test)]
mod test_qsort3 {
    fn check_sort(v1: &[mut int], v2: &[mut int]) {
        let len = vec::len::<int>(v1);
        quick_sort3::<int>(v1);
        let mut i = 0u;
        while i < len {
            log(debug, v2[i]);
            assert (v2[i] == v1[i]);
            i += 1u;
        }
    }

    #[test]
    fn test() {
        {
            let v1 = ~[mut 3, 7, 4, 5, 2, 9, 5, 8];
            let v2 = ~[mut 2, 3, 4, 5, 5, 7, 8, 9];
            check_sort(v1, v2);
        }
        {
            let v1 = ~[mut 1, 1, 1];
            let v2 = ~[mut 1, 1, 1];
            check_sort(v1, v2);
        }
        {
            let v1: ~[mut int] = ~[mut];
            let v2: ~[mut int] = ~[mut];
            check_sort(v1, v2);
        }
        { let v1 = ~[mut 9]; let v2 = ~[mut 9]; check_sort(v1, v2); }
        {
            let v1 = ~[mut 9, 3, 3, 3, 9];
            let v2 = ~[mut 3, 3, 3, 9, 9];
            check_sort(v1, v2);
        }
    }
}

#[cfg(test)]
mod test_qsort {
    fn check_sort(v1: &[mut int], v2: &[mut int]) {
        let len = vec::len::<int>(v1);
        pure fn leual(a: &int, b: &int) -> bool { *a <= *b }
        quick_sort::<int>(leual, v1);
        let mut i = 0u;
        while i < len {
            log(debug, v2[i]);
            assert (v2[i] == v1[i]);
            i += 1u;
        }
    }

    #[test]
    fn test() {
        {
            let v1 = ~[mut 3, 7, 4, 5, 2, 9, 5, 8];
            let v2 = ~[mut 2, 3, 4, 5, 5, 7, 8, 9];
            check_sort(v1, v2);
        }
        {
            let v1 = ~[mut 1, 1, 1];
            let v2 = ~[mut 1, 1, 1];
            check_sort(v1, v2);
        }
        {
            let v1: ~[mut int] = ~[mut];
            let v2: ~[mut int] = ~[mut];
            check_sort(v1, v2);
        }
        { let v1 = ~[mut 9]; let v2 = ~[mut 9]; check_sort(v1, v2); }
        {
            let v1 = ~[mut 9, 3, 3, 3, 9];
            let v2 = ~[mut 3, 3, 3, 9, 9];
            check_sort(v1, v2);
        }
    }

    // Regression test for #750
    #[test]
    fn test_simple() {
        let names = ~[mut 2, 1, 3];

        let expected = ~[1, 2, 3];

        sort::quick_sort(|x, y| { int::le(*x, *y) }, names);

        let immut_names = vec::from_mut(names);

        let pairs = vec::zip(expected, immut_names);
        for vec::each(pairs) |p| {
            let (a, b) = p;
            debug!("%d %d", a, b);
            assert (a == b);
        }
    }
}

#[cfg(test)]
mod tests {

    fn check_sort(v1: &[int], v2: &[int]) {
        let len = vec::len::<int>(v1);
        pure fn le(a: &int, b: &int) -> bool { *a <= *b }
        let f = le;
        let v3 = merge_sort::<int>(f, v1);
        let mut i = 0u;
        while i < len {
            log(debug, v3[i]);
            assert (v3[i] == v2[i]);
            i += 1u;
        }
    }

    #[test]
    fn test() {
        {
            let v1 = ~[3, 7, 4, 5, 2, 9, 5, 8];
            let v2 = ~[2, 3, 4, 5, 5, 7, 8, 9];
            check_sort(v1, v2);
        }
        { let v1 = ~[1, 1, 1]; let v2 = ~[1, 1, 1]; check_sort(v1, v2); }
        { let v1:~[int] = ~[]; let v2:~[int] = ~[]; check_sort(v1, v2); }
        { let v1 = ~[9]; let v2 = ~[9]; check_sort(v1, v2); }
        {
            let v1 = ~[9, 3, 3, 3, 9];
            let v2 = ~[3, 3, 3, 9, 9];
            check_sort(v1, v2);
        }
    }

    #[test]
    fn test_merge_sort_mutable() {
        pure fn le(a: &int, b: &int) -> bool { *a <= *b }
        let v1 = ~[mut 3, 2, 1];
        let v2 = merge_sort(le, v1);
        assert v2 == ~[1, 2, 3];
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>#[doc = "Generate markdown from a document tree"];

import std::io;
import std::io::writer_util;

export mk_pass;

fn mk_pass(
    writer: fn~() -> io::writer
) -> pass {
    ret fn~(
        _srv: astsrv::srv,
        doc: doc::cratedoc
    ) -> doc::cratedoc {
        write_markdown(doc, writer());
        doc
    };
}

type ctxt = {
    w: io::writer,
    mutable depth: uint
};

fn write_markdown(
    doc: doc::cratedoc,
    writer: io::writer
) {
    let ctxt = {
        w: writer,
        mutable depth: 1u
    };

    write_crate(ctxt, doc);
}

fn write_header(ctxt: ctxt, title: str) {
    let hashes = str::from_chars(vec::init_elt('#', ctxt.depth));
    ctxt.w.write_line(#fmt("%s %s", hashes, title));
    ctxt.w.write_line("");
}

fn subsection(ctxt: ctxt, f: fn&()) {
    ctxt.depth += 1u;
    f();
    ctxt.depth -= 1u;
}

fn write_crate(
    ctxt: ctxt,
    doc: doc::cratedoc
) {
    write_header(ctxt, #fmt("Crate %s", doc.topmod.name));
    write_top_module(ctxt, doc.topmod);
}

fn write_top_module(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_mod_contents(ctxt, moddoc);
}

fn write_mod(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_header(ctxt, #fmt("Module `%s`", moddoc.name));
    write_mod_contents(ctxt, moddoc);
}

fn write_mod_contents(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    for fndoc in *moddoc.fns {
        subsection(ctxt) {||
            write_fn(ctxt, fndoc);
        }
    }

    for moddoc in *moddoc.mods {
        subsection(ctxt) {||
            write_mod(ctxt, moddoc);
        }
    }
}

fn write_fn(
    ctxt: ctxt,
    doc: doc::fndoc
) {
    write_header(ctxt, #fmt("Function `%s`", doc.name));
    write_brief(ctxt, doc.brief);
    write_desc(ctxt, doc.desc);
    write_args(ctxt, doc.args);
    write_return(ctxt, doc.return);
}

fn write_brief(
    ctxt: ctxt,
    brief: option<str>
) {
    alt brief {
      some(brief) {
        ctxt.w.write_line(brief);
        ctxt.w.write_line("");
      }
      none. { }
    }
}

fn write_desc(
    ctxt: ctxt,
    desc: option<str>
) {
    alt desc {
        some(desc) {
            ctxt.w.write_line(desc);
            ctxt.w.write_line("");
        }
        none. { }
    }
}

fn write_args(
    ctxt: ctxt,
    args: [doc::argdoc]
) {
    for arg in args {
        ctxt.w.write_str("### Argument `" + arg.name + "`: ");
    }
}

fn write_return(
    ctxt: ctxt,
    return: option<doc::retdoc>
) {
    alt return {
      some(doc) {
        alt doc.ty {
          some(ty) {
            ctxt.w.write_line(#fmt("Returns `%s`", ty));
            ctxt.w.write_line("");
            alt doc.desc {
              some(d) {
                ctxt.w.write_line(d);
              }
              none. { }
            }
          }
          none. { fail "unimplemented"; }
        }
      }
      none. { }
    }
}

#[cfg(test)]
mod tests {
    fn render(source: str) -> str {
        let srv = astsrv::mk_srv_from_str(source);
        let doc = extract::from_srv(srv, "");
        let doc = attr_pass::mk_pass()(srv, doc);
        let doc = tystr_pass::mk_pass()(srv, doc);
        write_markdown_str(doc)
    }

    fn write_markdown_str(
        doc: doc::cratedoc
    ) -> str {
        let buffer = io::mk_mem_buffer();
        let writer = io::mem_buffer_writer(buffer);
        write_markdown(doc, writer);
        ret io::mem_buffer_str(buffer);
    }

    #[test]
    fn write_markdown_should_write_crate_header() {
        let srv = astsrv::mk_srv_from_str("");
        let doc = extract::from_srv(srv, "belch");
        let doc = attr_pass::mk_pass()(srv, doc);
        let markdown = write_markdown_str(doc);
        assert str::contains(markdown, "# Crate belch");
    }

    #[test]
    fn write_markdown_should_write_function_header() {
        let markdown = render("fn func() { }");
        assert str::contains(markdown, "## Function `func`");
    }

    #[test]
    fn write_markdown_should_write_mod_headers() {
        let markdown = render("mod moo { }");
        assert str::contains(markdown, "## Module `moo`");
    }

    #[test]
    fn should_leave_blank_line_after_header() {
        let markdown = render("mod morp { }");
        assert str::contains(markdown, "Module `morp`\n\n");
    }

    #[test]
    fn should_leave_blank_line_between_fn_header_and_brief() {
        let markdown = render("#[doc(brief = \"brief\")] fn a() { }");
        assert str::contains(markdown, "Function `a`\n\nbrief");
    }

    #[test]
    fn should_leave_blank_line_after_brief() {
        let markdown = render("#[doc(brief = \"brief\")] fn a() { }");
        assert str::contains(markdown, "brief\n\n");
    }

    #[test]
    fn should_leave_blank_line_between_brief_and_desc() {
        let markdown = render(
            "#[doc(brief = \"brief\", desc = \"desc\")] fn a() { }"
        );
        assert str::contains(markdown, "brief\n\ndesc");
    }

    #[test]
    fn should_write_return_type_on_new_line() {
        let markdown = render("fn a() -> int { }");
        assert str::contains(markdown, "\nReturns `int`");
    }

    #[test]
    fn should_write_blank_line_between_return_type_and_next_header() {
        let markdown = render(
            "fn a() -> int { } \
             fn b() -> int { }"
        );
        assert str::contains(markdown, "Returns `int`\n\n##");
    }
}<commit_msg>rustdoc: Write markdown for fn arguments<commit_after>#[doc = "Generate markdown from a document tree"];

import std::io;
import std::io::writer_util;

export mk_pass;

fn mk_pass(
    writer: fn~() -> io::writer
) -> pass {
    ret fn~(
        _srv: astsrv::srv,
        doc: doc::cratedoc
    ) -> doc::cratedoc {
        write_markdown(doc, writer());
        doc
    };
}

type ctxt = {
    w: io::writer,
    mutable depth: uint
};

fn write_markdown(
    doc: doc::cratedoc,
    writer: io::writer
) {
    let ctxt = {
        w: writer,
        mutable depth: 1u
    };

    write_crate(ctxt, doc);
}

fn write_header(ctxt: ctxt, title: str) {
    let hashes = str::from_chars(vec::init_elt('#', ctxt.depth));
    ctxt.w.write_line(#fmt("%s %s", hashes, title));
    ctxt.w.write_line("");
}

fn subsection(ctxt: ctxt, f: fn&()) {
    ctxt.depth += 1u;
    f();
    ctxt.depth -= 1u;
}

fn write_crate(
    ctxt: ctxt,
    doc: doc::cratedoc
) {
    write_header(ctxt, #fmt("Crate %s", doc.topmod.name));
    write_top_module(ctxt, doc.topmod);
}

fn write_top_module(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_mod_contents(ctxt, moddoc);
}

fn write_mod(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_header(ctxt, #fmt("Module `%s`", moddoc.name));
    write_mod_contents(ctxt, moddoc);
}

fn write_mod_contents(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    for fndoc in *moddoc.fns {
        subsection(ctxt) {||
            write_fn(ctxt, fndoc);
        }
    }

    for moddoc in *moddoc.mods {
        subsection(ctxt) {||
            write_mod(ctxt, moddoc);
        }
    }
}

fn write_fn(
    ctxt: ctxt,
    doc: doc::fndoc
) {
    write_header(ctxt, #fmt("Function `%s`", doc.name));
    write_brief(ctxt, doc.brief);
    write_desc(ctxt, doc.desc);
    write_args(ctxt, doc.args);
    write_return(ctxt, doc.return);
}

fn write_brief(
    ctxt: ctxt,
    brief: option<str>
) {
    alt brief {
      some(brief) {
        ctxt.w.write_line(brief);
        ctxt.w.write_line("");
      }
      none. { }
    }
}

fn write_desc(
    ctxt: ctxt,
    desc: option<str>
) {
    alt desc {
        some(desc) {
            ctxt.w.write_line(desc);
            ctxt.w.write_line("");
        }
        none. { }
    }
}

fn write_args(
    ctxt: ctxt,
    args: [doc::argdoc]
) {
    if vec::is_not_empty(args) {
        ctxt.w.write_line("Arguments:");
        ctxt.w.write_line("");
        vec::iter(args) {|arg| write_arg(ctxt, arg) };
        ctxt.w.write_line("");
    }
}

fn write_arg(ctxt: ctxt, arg: doc::argdoc) {
    ctxt.w.write_line(#fmt("* %s", arg.name));
}

#[test]
fn should_write_argument_list() {
    let source = "fn a(b: int, c: int) { }";
    let markdown = test::render(source);
    assert str::contains(
        markdown,
        "Arguments:\n\
         \n\
         * b\n\
         * c\n\
         \n"
    );
}

#[test]
fn should_not_write_arguments_if_none() {
    let source = "fn a() { } fn b() { }";
    let markdown = test::render(source);
    assert !str::contains(markdown, "Arguments");
}

fn write_return(
    ctxt: ctxt,
    return: option<doc::retdoc>
) {
    alt return {
      some(doc) {
        alt doc.ty {
          some(ty) {
            ctxt.w.write_line(#fmt("Returns `%s`", ty));
            ctxt.w.write_line("");
            alt doc.desc {
              some(d) {
                ctxt.w.write_line(d);
              }
              none. { }
            }
          }
          none. { fail "unimplemented"; }
        }
      }
      none. { }
    }
}

#[cfg(test)]
mod test {
    fn render(source: str) -> str {
        let srv = astsrv::mk_srv_from_str(source);
        let doc = extract::from_srv(srv, "");
        let doc = attr_pass::mk_pass()(srv, doc);
        let doc = tystr_pass::mk_pass()(srv, doc);
        let markdown = write_markdown_str(doc);
        #debug("markdown: %s", markdown);
        markdown
    }

    fn write_markdown_str(
        doc: doc::cratedoc
    ) -> str {
        let buffer = io::mk_mem_buffer();
        let writer = io::mem_buffer_writer(buffer);
        write_markdown(doc, writer);
        ret io::mem_buffer_str(buffer);
    }

    #[test]
    fn write_markdown_should_write_crate_header() {
        let srv = astsrv::mk_srv_from_str("");
        let doc = extract::from_srv(srv, "belch");
        let doc = attr_pass::mk_pass()(srv, doc);
        let markdown = write_markdown_str(doc);
        assert str::contains(markdown, "# Crate belch");
    }

    #[test]
    fn write_markdown_should_write_function_header() {
        let markdown = render("fn func() { }");
        assert str::contains(markdown, "## Function `func`");
    }

    #[test]
    fn write_markdown_should_write_mod_headers() {
        let markdown = render("mod moo { }");
        assert str::contains(markdown, "## Module `moo`");
    }

    #[test]
    fn should_leave_blank_line_after_header() {
        let markdown = render("mod morp { }");
        assert str::contains(markdown, "Module `morp`\n\n");
    }

    #[test]
    fn should_leave_blank_line_between_fn_header_and_brief() {
        let markdown = render("#[doc(brief = \"brief\")] fn a() { }");
        assert str::contains(markdown, "Function `a`\n\nbrief");
    }

    #[test]
    fn should_leave_blank_line_after_brief() {
        let markdown = render("#[doc(brief = \"brief\")] fn a() { }");
        assert str::contains(markdown, "brief\n\n");
    }

    #[test]
    fn should_leave_blank_line_between_brief_and_desc() {
        let markdown = render(
            "#[doc(brief = \"brief\", desc = \"desc\")] fn a() { }"
        );
        assert str::contains(markdown, "brief\n\ndesc");
    }

    #[test]
    fn should_write_return_type_on_new_line() {
        let markdown = render("fn a() -> int { }");
        assert str::contains(markdown, "\nReturns `int`");
    }

    #[test]
    fn should_write_blank_line_between_return_type_and_next_header() {
        let markdown = render(
            "fn a() -> int { } \
             fn b() -> int { }"
        );
        assert str::contains(markdown, "Returns `int`\n\n##");
    }
}<|endoftext|>


<commit_before><commit_msg>Remove Extensions from ListBoxRows<commit_after><|endoftext|>


<commit_before><commit_msg>:fire: Remove unused struct<commit_after><|endoftext|>


<commit_before><commit_msg>...actually commit tests<commit_after>// Copyright 2016 Mozilla Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use ::client::{
    connect_to_server,
};
use ::commands::{
    request_shutdown,
    request_stats,
};
use mio::Sender;
use ::server::{
    ServerMessage,
    create_server,
    run_server,
};
use std::thread;

fn run_server_thread() -> (u16, Sender<ServerMessage>, thread::JoinHandle<()>) {
    // Create a server, run it on a background thread.
    let (server, event_loop) = create_server(0).unwrap();
    assert!(server.port() > 0);
    let port = server.port();
    let sender = event_loop.channel();
    (port, sender, thread::spawn(move || {
        run_server(server, event_loop).unwrap()
    }))
}

#[test]
fn test_server_shutdown() {
    let (port, _, child) = run_server_thread();
    // Connect to the server.
    let conn = connect_to_server(port).unwrap();
    // Ask it to shut down
    request_shutdown(conn).unwrap();
    // Ensure that it shuts down.
    child.join().unwrap();
}

#[test]
fn test_server_stats() {
    let (port, sender, child) = run_server_thread();
    // Connect to the server.
    let conn = connect_to_server(port).unwrap();
    // Ask it for stats.
    let stats = request_stats(conn).unwrap();
    assert!(stats.get_stats().len() > 0);
    // Now signal it to shut down.
    sender.send(ServerMessage::Shutdown).unwrap();
    // Ensure that it shuts down.
    child.join().unwrap();
}
<|endoftext|>


<commit_before>use common::slice::GetSlice;

use alloc::boxed::Box;

use arch::memory::Memory;

use collections::slice;
use collections::string::{String, ToString};
use collections::vec::Vec;

use common::debug;

use core::cmp;

use disk::Disk;
use disk::ide::Extent;

use fs::redoxfs::{FileSystem, Node, NodeData};

use fs::{KScheme, Resource, ResourceSeek, Url, VecResource};

use syscall::{O_CREAT, O_TRUNC, MODE_DIR, MODE_FILE, Stat};

use system::error::{Error, Result, ENOENT, EIO};

/// A file resource
pub struct FileResource {
    pub scheme: *mut FileScheme,
    pub node: Node,
    pub vec: Vec<u8>,
    pub seek: usize,
    pub dirty: bool,
}

impl Resource for FileResource {
    fn dup(&self) -> Result<Box<Resource>> {
        Ok(box FileResource {
            scheme: self.scheme,
            node: self.node.clone(),
            vec: self.vec.clone(),
            seek: self.seek,
            dirty: self.dirty,
        })
    }

    fn path(&self, buf: &mut [u8]) -> Result<usize> {
        let path_a = b"file:/";
        let path_b = self.node.name.as_bytes();
        for (b, p) in buf.iter_mut().zip(path_a.iter().chain(path_b.iter())) {
            *b = *p;
        }

        Ok(cmp::min(buf.len(), path_a.len() + path_b.len()))
    }

    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        let mut i = 0;
        while i < buf.len() && self.seek < self.vec.len() {
            match self.vec.get(self.seek) {
                Some(b) => buf[i] = *b,
                None => (),
            }
            self.seek += 1;
            i += 1;
        }
        Ok(i)
    }

    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        let mut i = 0;
        while i < buf.len() && self.seek < self.vec.len() {
            self.vec[self.seek] = buf[i];
            self.seek += 1;
            i += 1;
        }
        while i < buf.len() {
            self.vec.push(buf[i]);
            self.seek += 1;
            i += 1;
        }
        if i > 0 {
            self.dirty = true;
        }
        Ok(i)
    }

    fn seek(&mut self, pos: ResourceSeek) -> Result<usize> {
        match pos {
            ResourceSeek::Start(offset) => self.seek = offset,
            ResourceSeek::Current(offset) =>
                self.seek = cmp::max(0, self.seek as isize + offset) as usize,
            ResourceSeek::End(offset) =>
                self.seek = cmp::max(0, self.vec.len() as isize + offset) as usize,
        }
        while self.vec.len() < self.seek {
            self.vec.push(0);
        }
        Ok(self.seek)
    }

    // TODO: Check to make sure proper amount of bytes written. See Disk::write
    fn sync(&mut self) -> Result<()> {
        if self.dirty {
            let mut node_dirty = false;
            let mut pos = 0;
            let mut remaining = self.vec.len() as isize;
            for ref mut extent in &mut self.node.extents {
                if remaining > 0 && extent.empty() {
                    debug::d("Reallocate file, extra: ");
                    debug::ds(remaining);
                    debug::dl();

                    unsafe {
                        let sectors = ((remaining + 511) / 512) as u64;
                        if (*self.scheme).fs.header.free_space.length >= sectors * 512 {
                            extent.block = (*self.scheme).fs.header.free_space.block;
                            extent.length = remaining as u64;
                            (*self.scheme).fs.header.free_space.block = (*self.scheme)
                                                                            .fs
                                                                            .header
                                                                            .free_space
                                                                            .block +
                                                                        sectors;
                            (*self.scheme).fs.header.free_space.length = (*self.scheme)
                                                                             .fs
                                                                             .header
                                                                             .free_space
                                                                             .length -
                                                                         sectors * 512;

                            node_dirty = true;
                        }
                    }
                }

                // Make sure it is a valid extent
                if !extent.empty() {
                    let current_sectors = (extent.length as usize + 511) / 512;
                    let max_size = current_sectors * 512;

                    let size = cmp::min(remaining as usize, max_size);

                    if size as u64 != extent.length {
                        extent.length = size as u64;
                        node_dirty = true;
                    }

                    while self.vec.len() < pos + max_size {
                        self.vec.push(0);
                    }

                    unsafe {
                        let _ = (*self.scheme).fs.disk.write(extent.block, &self.vec[pos .. pos + max_size]);
                    }

                    self.vec.truncate(pos + size);

                    pos += size;
                    remaining -= size as isize;
                }
            }

            if node_dirty {
                debug::d("Node dirty, rewrite\n");

                if self.node.block > 0 {
                    unsafe {
                        if let Some(mut node_data) = Memory::<NodeData>::new(1) {
                            node_data.write(0, self.node.data());

                            let mut buffer = slice::from_raw_parts(node_data.address() as *mut u8, 512);
                            let _ = (*self.scheme).fs.disk.write(self.node.block, &mut buffer);

                            debug::d("Renode\n");

                            for mut node in (*self.scheme).fs.nodes.iter_mut() {
                                if node.block == self.node.block {
                                    *node = self.node.clone();
                                }
                            }
                        }
                    }
                } else {
                    debug::d("Need to place Node block\n");
                }
            }

            self.dirty = false;

            if remaining > 0 {
                debug::d("Need to defragment file, extra: ");
                debug::ds(remaining);
                debug::dl();
                return Err(Error::new(EIO));
            }
        }
        Ok(())
    }

    fn truncate(&mut self, len: usize) -> Result<()> {
        while len > self.vec.len() {
            self.vec.push(0);
        }
        self.vec.truncate(len);
        self.seek = cmp::min(self.seek, self.vec.len());
        self.dirty = true;
        Ok(())
    }
}

impl Drop for FileResource {
    fn drop(&mut self) {
        let _ = self.sync();
    }
}

/// A file scheme (pci + fs)
pub struct FileScheme {
    fs: FileSystem,
}

impl FileScheme {
    /// Create a new file scheme from an array of Disks
    pub fn new(mut disks: Vec<Box<Disk>>) -> Option<Box<Self>> {
        while ! disks.is_empty() {
            let disk = disks.remove(0);
            let name = disk.name();
            match FileSystem::from_disk(disk) {
                Ok(fs) => return Some(box FileScheme { fs: fs }),
                Err(err) => debugln!("{}: {}", name, err)
            }
        }

        None
    }
}

impl KScheme for FileScheme {
    fn on_irq(&mut self, _irq: u8) {
        /*if irq == self.fs.disk.irq {
        }*/
    }

    fn scheme(&self) -> &str {
        "file"
    }

    fn open(&mut self, url: Url, flags: usize) -> Result<Box<Resource>> {
        let path = url.reference().trim_matches('/');

        let children = self.fs.list(path);
        if ! children.is_empty() {
            let mut list = String::new();
            let mut dirs: Vec<String> = Vec::new();

            for file in children.iter() {
                let mut line = String::new();
                match file.find('/') {
                    Some(index) => {
                        let dirname = file.get_slice(..index + 1).to_string();
                        let mut found = false;
                        for dir in dirs.iter() {
                            if dirname == *dir {
                                found = true;
                                break;
                            }
                        }
                        if found {
                            line.clear();
                        } else {
                            line = dirname.clone();
                            dirs.push(dirname);
                        }
                    }
                    None => line = file.clone(),
                }
                if !line.is_empty() {
                    if !list.is_empty() {
                        list = list + "\n" + &line;
                    } else {
                        list = line;
                    }
                }
            }

            if list.len() > 0 {
                Ok(box VecResource::new(url.to_string(), list.into_bytes()))
            } else {
                Err(Error::new(ENOENT))
            }
        } else {
            match self.fs.node(path) {
                Some(node) => {
                    let mut vec: Vec<u8> = Vec::new();
                    for extent in &node.extents {
                        if extent.block > 0 && extent.length > 0 {
                            let current_sectors = (extent.length as usize + 511) / 512;
                            let max_size = current_sectors * 512;

                            let size = cmp::min(extent.length as usize, max_size);

                            let pos = vec.len();

                            while vec.len() < pos + max_size {
                                vec.push(0);
                            }

                            let _ = self.fs.disk.read(extent.block, &mut vec[pos..pos + max_size]);

                            vec.truncate(pos + size);
                        }
                    }

                    let mut resource = box FileResource {
                        scheme: self,
                        node: node,
                        vec: vec,
                        seek: 0,
                        dirty: false,
                    };

                    if flags & O_TRUNC == O_TRUNC {
                        try!(resource.truncate(0));
                    }

                    Ok(resource)
                }
                None => {
                    if flags & O_CREAT == O_CREAT {
                        // TODO: Create file
                        let mut node = Node {
                            block: 0,
                            name: path.to_string(),
                            extents: [Extent {
                                block: 0,
                                length: 0,
                            }; 16],
                        };

                        if self.fs.header.free_space.length >= 512 {
                            node.block = self.fs.header.free_space.block;
                            self.fs.header.free_space.block = self.fs.header.free_space.block + 1;
                            self.fs.header.free_space.length = self.fs.header.free_space.length -
                                                               512;
                        }

                        self.fs.nodes.push(node.clone());

                        Ok(box FileResource {
                            scheme: self,
                            node: node,
                            vec: Vec::new(),
                            seek: 0,
                            dirty: false,
                        })
                    } else {
                        Err(Error::new(ENOENT))
                    }
                }
            }
        }
    }

    fn stat(&mut self, url: Url, stat: &mut Stat) -> Result<()> {
        let path = url.reference().trim_matches('/');

        let children = self.fs.list(path);
        if ! children.is_empty() {
            let mut list = String::new();
            let mut dirs: Vec<String> = Vec::new();

            for file in children.iter() {
                let mut line = String::new();
                match file.find('/') {
                    Some(index) => {
                        let dirname = file.get_slice(..index + 1).to_string();
                        let mut found = false;
                        for dir in dirs.iter() {
                            if dirname == *dir {
                                found = true;
                                break;
                            }
                        }
                        if found {
                            line.clear();
                        } else {
                            line = dirname.clone();
                            dirs.push(dirname);
                        }
                    }
                    None => line = file.clone(),
                }
                if !line.is_empty() {
                    if !list.is_empty() {
                        list = list + "\n" + &line;
                    } else {
                        list = line;
                    }
                }
            }

            if list.len() > 0 {
                stat.st_mode = MODE_DIR;
                stat.st_size = list.len() as u64;

                Ok(())
            } else {
                Err(Error::new(ENOENT))
            }
        } else {
            match self.fs.node(path) {
                Some(node) => {
                    stat.st_mode = MODE_FILE;
                    stat.st_size = 0;

                    for extent in &node.extents {
                        if extent.block > 0 && extent.length > 0 {
                            stat.st_size += extent.length;
                        }
                    }

                    Ok(())
                }
                None => Err(Error::new(ENOENT))
            }
        }
    }

    fn unlink(&mut self, url: Url) -> Result<()> {
        let mut ret = Err(Error::new(ENOENT));

        let path = url.reference().trim_matches('/');

        let mut i = 0;
        while i < self.fs.nodes.len() {
            let mut remove = false;

            if let Some(node) = self.fs.nodes.get(i) {
                remove = node.name == path;
            }

            if remove {
                self.fs.nodes.remove(i);
                ret = Ok(());
            } else {
                i += 1;
            }
        }

        ret
    }
}
<commit_msg>Comment out write messages<commit_after>use common::slice::GetSlice;

use alloc::boxed::Box;

use arch::memory::Memory;

use collections::slice;
use collections::string::{String, ToString};
use collections::vec::Vec;

use common::debug;

use core::cmp;

use disk::Disk;
use disk::ide::Extent;

use fs::redoxfs::{FileSystem, Node, NodeData};

use fs::{KScheme, Resource, ResourceSeek, Url, VecResource};

use syscall::{O_CREAT, O_TRUNC, MODE_DIR, MODE_FILE, Stat};

use system::error::{Error, Result, ENOENT, EIO};

/// A file resource
pub struct FileResource {
    pub scheme: *mut FileScheme,
    pub node: Node,
    pub vec: Vec<u8>,
    pub seek: usize,
    pub dirty: bool,
}

impl Resource for FileResource {
    fn dup(&self) -> Result<Box<Resource>> {
        Ok(box FileResource {
            scheme: self.scheme,
            node: self.node.clone(),
            vec: self.vec.clone(),
            seek: self.seek,
            dirty: self.dirty,
        })
    }

    fn path(&self, buf: &mut [u8]) -> Result<usize> {
        let path_a = b"file:/";
        let path_b = self.node.name.as_bytes();
        for (b, p) in buf.iter_mut().zip(path_a.iter().chain(path_b.iter())) {
            *b = *p;
        }

        Ok(cmp::min(buf.len(), path_a.len() + path_b.len()))
    }

    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        let mut i = 0;
        while i < buf.len() && self.seek < self.vec.len() {
            match self.vec.get(self.seek) {
                Some(b) => buf[i] = *b,
                None => (),
            }
            self.seek += 1;
            i += 1;
        }
        Ok(i)
    }

    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        let mut i = 0;
        while i < buf.len() && self.seek < self.vec.len() {
            self.vec[self.seek] = buf[i];
            self.seek += 1;
            i += 1;
        }
        while i < buf.len() {
            self.vec.push(buf[i]);
            self.seek += 1;
            i += 1;
        }
        if i > 0 {
            self.dirty = true;
        }
        Ok(i)
    }

    fn seek(&mut self, pos: ResourceSeek) -> Result<usize> {
        match pos {
            ResourceSeek::Start(offset) => self.seek = offset,
            ResourceSeek::Current(offset) =>
                self.seek = cmp::max(0, self.seek as isize + offset) as usize,
            ResourceSeek::End(offset) =>
                self.seek = cmp::max(0, self.vec.len() as isize + offset) as usize,
        }
        while self.vec.len() < self.seek {
            self.vec.push(0);
        }
        Ok(self.seek)
    }

    // TODO: Check to make sure proper amount of bytes written. See Disk::write
    fn sync(&mut self) -> Result<()> {
        if self.dirty {
            let mut node_dirty = false;
            let mut pos = 0;
            let mut remaining = self.vec.len() as isize;
            for ref mut extent in &mut self.node.extents {
                if remaining > 0 && extent.empty() {
                    /*
                    debug::d("Reallocate file, extra: ");
                    debug::ds(remaining);
                    debug::dl();
                    */

                    unsafe {
                        let sectors = ((remaining + 511) / 512) as u64;
                        if (*self.scheme).fs.header.free_space.length >= sectors * 512 {
                            extent.block = (*self.scheme).fs.header.free_space.block;
                            extent.length = remaining as u64;
                            (*self.scheme).fs.header.free_space.block = (*self.scheme)
                                                                            .fs
                                                                            .header
                                                                            .free_space
                                                                            .block +
                                                                        sectors;
                            (*self.scheme).fs.header.free_space.length = (*self.scheme)
                                                                             .fs
                                                                             .header
                                                                             .free_space
                                                                             .length -
                                                                         sectors * 512;

                            node_dirty = true;
                        }
                    }
                }

                // Make sure it is a valid extent
                if !extent.empty() {
                    let current_sectors = (extent.length as usize + 511) / 512;
                    let max_size = current_sectors * 512;

                    let size = cmp::min(remaining as usize, max_size);

                    if size as u64 != extent.length {
                        extent.length = size as u64;
                        node_dirty = true;
                    }

                    while self.vec.len() < pos + max_size {
                        self.vec.push(0);
                    }

                    unsafe {
                        let _ = (*self.scheme).fs.disk.write(extent.block, &self.vec[pos .. pos + max_size]);
                    }

                    self.vec.truncate(pos + size);

                    pos += size;
                    remaining -= size as isize;
                }
            }

            if node_dirty {
                //debug::d("Node dirty, rewrite\n");

                if self.node.block > 0 {
                    unsafe {
                        if let Some(mut node_data) = Memory::<NodeData>::new(1) {
                            node_data.write(0, self.node.data());

                            let mut buffer = slice::from_raw_parts(node_data.address() as *mut u8, 512);
                            let _ = (*self.scheme).fs.disk.write(self.node.block, &mut buffer);

                            //debug::d("Renode\n");

                            for mut node in (*self.scheme).fs.nodes.iter_mut() {
                                if node.block == self.node.block {
                                    *node = self.node.clone();
                                }
                            }
                        }
                    }
                } else {
                    debug::d("Need to place Node block\n");
                }
            }

            self.dirty = false;

            if remaining > 0 {
                debug::d("Need to defragment file, extra: ");
                debug::ds(remaining);
                debug::dl();
                return Err(Error::new(EIO));
            }
        }
        Ok(())
    }

    fn truncate(&mut self, len: usize) -> Result<()> {
        while len > self.vec.len() {
            self.vec.push(0);
        }
        self.vec.truncate(len);
        self.seek = cmp::min(self.seek, self.vec.len());
        self.dirty = true;
        Ok(())
    }
}

impl Drop for FileResource {
    fn drop(&mut self) {
        let _ = self.sync();
    }
}

/// A file scheme (pci + fs)
pub struct FileScheme {
    fs: FileSystem,
}

impl FileScheme {
    /// Create a new file scheme from an array of Disks
    pub fn new(mut disks: Vec<Box<Disk>>) -> Option<Box<Self>> {
        while ! disks.is_empty() {
            let disk = disks.remove(0);
            let name = disk.name();
            match FileSystem::from_disk(disk) {
                Ok(fs) => return Some(box FileScheme { fs: fs }),
                Err(err) => debugln!("{}: {}", name, err)
            }
        }

        None
    }
}

impl KScheme for FileScheme {
    fn on_irq(&mut self, _irq: u8) {
        /*if irq == self.fs.disk.irq {
        }*/
    }

    fn scheme(&self) -> &str {
        "file"
    }

    fn open(&mut self, url: Url, flags: usize) -> Result<Box<Resource>> {
        let path = url.reference().trim_matches('/');

        let children = self.fs.list(path);
        if ! children.is_empty() {
            let mut list = String::new();
            let mut dirs: Vec<String> = Vec::new();

            for file in children.iter() {
                let mut line = String::new();
                match file.find('/') {
                    Some(index) => {
                        let dirname = file.get_slice(..index + 1).to_string();
                        let mut found = false;
                        for dir in dirs.iter() {
                            if dirname == *dir {
                                found = true;
                                break;
                            }
                        }
                        if found {
                            line.clear();
                        } else {
                            line = dirname.clone();
                            dirs.push(dirname);
                        }
                    }
                    None => line = file.clone(),
                }
                if !line.is_empty() {
                    if !list.is_empty() {
                        list = list + "\n" + &line;
                    } else {
                        list = line;
                    }
                }
            }

            if list.len() > 0 {
                Ok(box VecResource::new(url.to_string(), list.into_bytes()))
            } else {
                Err(Error::new(ENOENT))
            }
        } else {
            match self.fs.node(path) {
                Some(node) => {
                    let mut vec: Vec<u8> = Vec::new();
                    for extent in &node.extents {
                        if extent.block > 0 && extent.length > 0 {
                            let current_sectors = (extent.length as usize + 511) / 512;
                            let max_size = current_sectors * 512;

                            let size = cmp::min(extent.length as usize, max_size);

                            let pos = vec.len();

                            while vec.len() < pos + max_size {
                                vec.push(0);
                            }

                            let _ = self.fs.disk.read(extent.block, &mut vec[pos..pos + max_size]);

                            vec.truncate(pos + size);
                        }
                    }

                    let mut resource = box FileResource {
                        scheme: self,
                        node: node,
                        vec: vec,
                        seek: 0,
                        dirty: false,
                    };

                    if flags & O_TRUNC == O_TRUNC {
                        try!(resource.truncate(0));
                    }

                    Ok(resource)
                }
                None => {
                    if flags & O_CREAT == O_CREAT {
                        // TODO: Create file
                        let mut node = Node {
                            block: 0,
                            name: path.to_string(),
                            extents: [Extent {
                                block: 0,
                                length: 0,
                            }; 16],
                        };

                        if self.fs.header.free_space.length >= 512 {
                            node.block = self.fs.header.free_space.block;
                            self.fs.header.free_space.block = self.fs.header.free_space.block + 1;
                            self.fs.header.free_space.length = self.fs.header.free_space.length -
                                                               512;
                        }

                        self.fs.nodes.push(node.clone());

                        Ok(box FileResource {
                            scheme: self,
                            node: node,
                            vec: Vec::new(),
                            seek: 0,
                            dirty: false,
                        })
                    } else {
                        Err(Error::new(ENOENT))
                    }
                }
            }
        }
    }

    fn stat(&mut self, url: Url, stat: &mut Stat) -> Result<()> {
        let path = url.reference().trim_matches('/');

        let children = self.fs.list(path);
        if ! children.is_empty() {
            let mut list = String::new();
            let mut dirs: Vec<String> = Vec::new();

            for file in children.iter() {
                let mut line = String::new();
                match file.find('/') {
                    Some(index) => {
                        let dirname = file.get_slice(..index + 1).to_string();
                        let mut found = false;
                        for dir in dirs.iter() {
                            if dirname == *dir {
                                found = true;
                                break;
                            }
                        }
                        if found {
                            line.clear();
                        } else {
                            line = dirname.clone();
                            dirs.push(dirname);
                        }
                    }
                    None => line = file.clone(),
                }
                if !line.is_empty() {
                    if !list.is_empty() {
                        list = list + "\n" + &line;
                    } else {
                        list = line;
                    }
                }
            }

            if list.len() > 0 {
                stat.st_mode = MODE_DIR;
                stat.st_size = list.len() as u64;

                Ok(())
            } else {
                Err(Error::new(ENOENT))
            }
        } else {
            match self.fs.node(path) {
                Some(node) => {
                    stat.st_mode = MODE_FILE;
                    stat.st_size = 0;

                    for extent in &node.extents {
                        if extent.block > 0 && extent.length > 0 {
                            stat.st_size += extent.length;
                        }
                    }

                    Ok(())
                }
                None => Err(Error::new(ENOENT))
            }
        }
    }

    fn unlink(&mut self, url: Url) -> Result<()> {
        let mut ret = Err(Error::new(ENOENT));

        let path = url.reference().trim_matches('/');

        let mut i = 0;
        while i < self.fs.nodes.len() {
            let mut remove = false;

            if let Some(node) = self.fs.nodes.get(i) {
                remove = node.name == path;
            }

            if remove {
                self.fs.nodes.remove(i);
                ret = Ok(());
            } else {
                i += 1;
            }
        }

        ret
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-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 rustc::mir::{self, Location, Mir};
use rustc::mir::visit::Visitor;
use rustc::ty::{Region, TyCtxt};
use rustc::ty::RegionKind;
use rustc::ty::RegionKind::ReScope;
use rustc::util::nodemap::{FxHashMap, FxHashSet};

use rustc_data_structures::bitslice::{BitwiseOperator};
use rustc_data_structures::indexed_set::{IdxSet};
use rustc_data_structures::indexed_vec::{IndexVec};

use dataflow::{BitDenotation, BlockSets, DataflowOperator};
pub use dataflow::indexes::BorrowIndex;

use syntax_pos::Span;

use std::fmt;

// `Borrows` maps each dataflow bit to an `Rvalue::Ref`, which can be
// uniquely identified in the MIR by the `Location` of the assigment
// statement in which it appears on the right hand side.
pub struct Borrows<'a, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    mir: &'a Mir<'tcx>,
    borrows: IndexVec<BorrowIndex, BorrowData<'tcx>>,
    location_map: FxHashMap<Location, BorrowIndex>,
    region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
    region_span_map: FxHashMap<RegionKind, Span>,
}

// temporarily allow some dead fields: `kind` and `region` will be
// needed by borrowck; `lvalue` will probably be a MovePathIndex when
// that is extended to include borrowed data paths.
#[allow(dead_code)]
#[derive(Debug)]
pub struct BorrowData<'tcx> {
    pub(crate) location: Location,
    pub(crate) kind: mir::BorrowKind,
    pub(crate) region: Region<'tcx>,
    pub(crate) lvalue: mir::Lvalue<'tcx>,
}

impl<'tcx> fmt::Display for BorrowData<'tcx> {
    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
        let kind = match self.kind {
            mir::BorrowKind::Shared => "",
            mir::BorrowKind::Unique => "uniq ",
            mir::BorrowKind::Mut => "mut ",
        };
        let region = format!("{}", self.region);
        let region = if region.len() > 0 { format!("{} ", region) } else { region };
        write!(w, "&{}{}{:?}", region, kind, self.lvalue)
    }
}

impl<'a, 'tcx> Borrows<'a, 'tcx> {
    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
        let mut visitor = GatherBorrows { idx_vec: IndexVec::new(),
                                          location_map: FxHashMap(),
                                          region_map: FxHashMap(),
                                          region_span_map: FxHashMap()};
        visitor.visit_mir(mir);
        return Borrows { tcx: tcx,
                         mir: mir,
                         borrows: visitor.idx_vec,
                         location_map: visitor.location_map,
                         region_map: visitor.region_map,
                         region_span_map: visitor.region_span_map};

        struct GatherBorrows<'tcx> {
            idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
            location_map: FxHashMap<Location, BorrowIndex>,
            region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
            region_span_map: FxHashMap<RegionKind, Span>,
        }
        impl<'tcx> Visitor<'tcx> for GatherBorrows<'tcx> {
            fn visit_rvalue(&mut self,
                            rvalue: &mir::Rvalue<'tcx>,
                            location: mir::Location) {
                if let mir::Rvalue::Ref(region, kind, ref lvalue) = *rvalue {
                    let borrow = BorrowData {
                        location: location, kind: kind, region: region, lvalue: lvalue.clone(),
                    };
                    let idx = self.idx_vec.push(borrow);
                    self.location_map.insert(location, idx);
                    let borrows = self.region_map.entry(region).or_insert(FxHashSet());
                    borrows.insert(idx);
                }
            }

            fn visit_statement(&mut self,
                               block: mir::BasicBlock,
                               statement: &mir::Statement<'tcx>,
                               location: Location) {
                if let mir::StatementKind::EndRegion(region_scope) = statement.kind {
                    self.region_span_map.insert(ReScope(region_scope), statement.source_info.span);
                }
                self.super_statement(block, statement, location);
            }
        }
    }

    pub fn borrows(&self) -> &IndexVec<BorrowIndex, BorrowData<'tcx>> { &self.borrows }

    pub fn location(&self, idx: BorrowIndex) -> &Location {
        &self.borrows[idx].location
    }

    pub fn region_span(&self, region: &Region) -> Span {
        let opt_span = self.region_span_map.get(region);
        assert!(opt_span.is_some(), "end region not found for {:?}", region);
        *opt_span.unwrap()
    }
}

impl<'a, 'tcx> BitDenotation for Borrows<'a, 'tcx> {
    type Idx = BorrowIndex;
    fn name() -> &'static str { "borrows" }
    fn bits_per_block(&self) -> usize {
        self.borrows.len()
    }
    fn start_block_effect(&self, _sets: &mut BlockSets<BorrowIndex>)  {
        // no borrows of code region_scopes have been taken prior to
        // function execution, so this method has no effect on
        // `_sets`.
    }
    fn statement_effect(&self,
                        sets: &mut BlockSets<BorrowIndex>,
                        location: Location) {
        let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| {
            panic!("could not find block at location {:?}", location);
        });
        let stmt = block.statements.get(location.statement_index).unwrap_or_else(|| {
            panic!("could not find statement at location {:?}");
        });
        match stmt.kind {
            mir::StatementKind::EndRegion(region_scope) => {
                let borrow_indexes = self.region_map.get(&ReScope(region_scope)).unwrap_or_else(|| {
                    panic!("could not find BorrowIndexs for region scope {:?}", region_scope);
                });

                for idx in borrow_indexes { sets.kill(&idx); }
            }

            mir::StatementKind::Assign(_, ref rhs) => {
                if let mir::Rvalue::Ref(region, _, _) = *rhs {
                    let index = self.location_map.get(&location).unwrap_or_else(|| {
                        panic!("could not find BorrowIndex for location {:?}", location);
                    });
                    assert!(self.region_map.get(region).unwrap_or_else(|| {
                        panic!("could not find BorrowIndexs for region {:?}", region);
                    }).contains(&index));
                    sets.gen(&index);
                }
            }

            mir::StatementKind::InlineAsm { .. } |
            mir::StatementKind::SetDiscriminant { .. } |
            mir::StatementKind::StorageLive(..) |
            mir::StatementKind::StorageDead(..) |
            mir::StatementKind::Validate(..) |
            mir::StatementKind::Nop => {}

        }
    }
    fn terminator_effect(&self,
                         _sets: &mut BlockSets<BorrowIndex>,
                         _location: Location) {
        // no terminators start nor end region scopes.
    }

    fn propagate_call_return(&self,
                             _in_out: &mut IdxSet<BorrowIndex>,
                             _call_bb: mir::BasicBlock,
                             _dest_bb: mir::BasicBlock,
                             _dest_lval: &mir::Lvalue) {
        // there are no effects on the region scopes from method calls.
    }
}

impl<'a, 'tcx> BitwiseOperator for Borrows<'a, 'tcx> {
    #[inline]
    fn join(&self, pred1: usize, pred2: usize) -> usize {
        pred1 | pred2 // union effects of preds when computing borrows
    }
}

impl<'a, 'tcx> DataflowOperator for Borrows<'a, 'tcx> {
    #[inline]
    fn bottom_value() -> bool {
        false // bottom = no Rvalue::Refs are active by default
    }
}
<commit_msg>Rollup merge of #44987 - pnkfelix:mir-borrowck-fix-borrowindexes-ice, r=arielb1<commit_after>// Copyright 2012-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 rustc::mir::{self, Location, Mir};
use rustc::mir::visit::Visitor;
use rustc::ty::{Region, TyCtxt};
use rustc::ty::RegionKind;
use rustc::ty::RegionKind::ReScope;
use rustc::util::nodemap::{FxHashMap, FxHashSet};

use rustc_data_structures::bitslice::{BitwiseOperator};
use rustc_data_structures::indexed_set::{IdxSet};
use rustc_data_structures::indexed_vec::{IndexVec};

use dataflow::{BitDenotation, BlockSets, DataflowOperator};
pub use dataflow::indexes::BorrowIndex;

use syntax_pos::Span;

use std::fmt;

// `Borrows` maps each dataflow bit to an `Rvalue::Ref`, which can be
// uniquely identified in the MIR by the `Location` of the assigment
// statement in which it appears on the right hand side.
pub struct Borrows<'a, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    mir: &'a Mir<'tcx>,
    borrows: IndexVec<BorrowIndex, BorrowData<'tcx>>,
    location_map: FxHashMap<Location, BorrowIndex>,
    region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
    region_span_map: FxHashMap<RegionKind, Span>,
}

// temporarily allow some dead fields: `kind` and `region` will be
// needed by borrowck; `lvalue` will probably be a MovePathIndex when
// that is extended to include borrowed data paths.
#[allow(dead_code)]
#[derive(Debug)]
pub struct BorrowData<'tcx> {
    pub(crate) location: Location,
    pub(crate) kind: mir::BorrowKind,
    pub(crate) region: Region<'tcx>,
    pub(crate) lvalue: mir::Lvalue<'tcx>,
}

impl<'tcx> fmt::Display for BorrowData<'tcx> {
    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
        let kind = match self.kind {
            mir::BorrowKind::Shared => "",
            mir::BorrowKind::Unique => "uniq ",
            mir::BorrowKind::Mut => "mut ",
        };
        let region = format!("{}", self.region);
        let region = if region.len() > 0 { format!("{} ", region) } else { region };
        write!(w, "&{}{}{:?}", region, kind, self.lvalue)
    }
}

impl<'a, 'tcx> Borrows<'a, 'tcx> {
    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
        let mut visitor = GatherBorrows { idx_vec: IndexVec::new(),
                                          location_map: FxHashMap(),
                                          region_map: FxHashMap(),
                                          region_span_map: FxHashMap()};
        visitor.visit_mir(mir);
        return Borrows { tcx: tcx,
                         mir: mir,
                         borrows: visitor.idx_vec,
                         location_map: visitor.location_map,
                         region_map: visitor.region_map,
                         region_span_map: visitor.region_span_map};

        struct GatherBorrows<'tcx> {
            idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
            location_map: FxHashMap<Location, BorrowIndex>,
            region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
            region_span_map: FxHashMap<RegionKind, Span>,
        }
        impl<'tcx> Visitor<'tcx> for GatherBorrows<'tcx> {
            fn visit_rvalue(&mut self,
                            rvalue: &mir::Rvalue<'tcx>,
                            location: mir::Location) {
                if let mir::Rvalue::Ref(region, kind, ref lvalue) = *rvalue {
                    let borrow = BorrowData {
                        location: location, kind: kind, region: region, lvalue: lvalue.clone(),
                    };
                    let idx = self.idx_vec.push(borrow);
                    self.location_map.insert(location, idx);
                    let borrows = self.region_map.entry(region).or_insert(FxHashSet());
                    borrows.insert(idx);
                }
            }

            fn visit_statement(&mut self,
                               block: mir::BasicBlock,
                               statement: &mir::Statement<'tcx>,
                               location: Location) {
                if let mir::StatementKind::EndRegion(region_scope) = statement.kind {
                    self.region_span_map.insert(ReScope(region_scope), statement.source_info.span);
                }
                self.super_statement(block, statement, location);
            }
        }
    }

    pub fn borrows(&self) -> &IndexVec<BorrowIndex, BorrowData<'tcx>> { &self.borrows }

    pub fn location(&self, idx: BorrowIndex) -> &Location {
        &self.borrows[idx].location
    }

    pub fn region_span(&self, region: &Region) -> Span {
        let opt_span = self.region_span_map.get(region);
        assert!(opt_span.is_some(), "end region not found for {:?}", region);
        *opt_span.unwrap()
    }
}

impl<'a, 'tcx> BitDenotation for Borrows<'a, 'tcx> {
    type Idx = BorrowIndex;
    fn name() -> &'static str { "borrows" }
    fn bits_per_block(&self) -> usize {
        self.borrows.len()
    }
    fn start_block_effect(&self, _sets: &mut BlockSets<BorrowIndex>)  {
        // no borrows of code region_scopes have been taken prior to
        // function execution, so this method has no effect on
        // `_sets`.
    }
    fn statement_effect(&self,
                        sets: &mut BlockSets<BorrowIndex>,
                        location: Location) {
        let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| {
            panic!("could not find block at location {:?}", location);
        });
        let stmt = block.statements.get(location.statement_index).unwrap_or_else(|| {
            panic!("could not find statement at location {:?}");
        });
        match stmt.kind {
            mir::StatementKind::EndRegion(region_scope) => {
                if let Some(borrow_indexes) = self.region_map.get(&ReScope(region_scope)) {
                    for idx in borrow_indexes { sets.kill(&idx); }
                } else {
                    // (if there is no entry, then there are no borrows to be tracked)
                }
            }

            mir::StatementKind::Assign(_, ref rhs) => {
                if let mir::Rvalue::Ref(region, _, _) = *rhs {
                    let index = self.location_map.get(&location).unwrap_or_else(|| {
                        panic!("could not find BorrowIndex for location {:?}", location);
                    });
                    assert!(self.region_map.get(region).unwrap_or_else(|| {
                        panic!("could not find BorrowIndexs for region {:?}", region);
                    }).contains(&index));
                    sets.gen(&index);
                }
            }

            mir::StatementKind::InlineAsm { .. } |
            mir::StatementKind::SetDiscriminant { .. } |
            mir::StatementKind::StorageLive(..) |
            mir::StatementKind::StorageDead(..) |
            mir::StatementKind::Validate(..) |
            mir::StatementKind::Nop => {}

        }
    }
    fn terminator_effect(&self,
                         _sets: &mut BlockSets<BorrowIndex>,
                         _location: Location) {
        // no terminators start nor end region scopes.
    }

    fn propagate_call_return(&self,
                             _in_out: &mut IdxSet<BorrowIndex>,
                             _call_bb: mir::BasicBlock,
                             _dest_bb: mir::BasicBlock,
                             _dest_lval: &mir::Lvalue) {
        // there are no effects on the region scopes from method calls.
    }
}

impl<'a, 'tcx> BitwiseOperator for Borrows<'a, 'tcx> {
    #[inline]
    fn join(&self, pred1: usize, pred2: usize) -> usize {
        pred1 | pred2 // union effects of preds when computing borrows
    }
}

impl<'a, 'tcx> DataflowOperator for Borrows<'a, 'tcx> {
    #[inline]
    fn bottom_value() -> bool {
        false // bottom = no Rvalue::Refs are active by default
    }
}
<|endoftext|>


<commit_before><commit_msg>type not required<commit_after><|endoftext|>


<commit_before><commit_msg>also test transmutes to empty enums<commit_after>#![feature(never_type)]
#![allow(unreachable_code)]
#![allow(unused_variables)]

enum Void {}

fn f(v: Void) -> ! {
    match v {}
}

fn main() {
    let v: Void = unsafe {
        std::mem::transmute::<(), Void>(()) //~ ERROR entered unreachable code
    };
    f(v);
}
<|endoftext|>


<commit_before><commit_msg>Add additional mode for debugging events<commit_after><|endoftext|>