<commit_before>//! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`.
mod lower;

use std::{iter, sync::Arc};

use hir_expand::{
    hygiene::Hygiene,
    name::{AsName, Name},
};
use ra_db::CrateId;
use ra_syntax::ast;

use crate::{type_ref::TypeRef, InFile};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ModPath {
    pub kind: PathKind,
    pub segments: Vec<Name>,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum PathKind {
    Plain,
    /// `self::` is `Super(0)`
    Super(u8),
    Crate,
    /// Absolute path (::foo)
    Abs,
    /// `$crate` from macro expansion
    DollarCrate(CrateId),
}

impl ModPath {
    pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> {
        lower::lower_path(path, hygiene).map(|it| it.mod_path)
    }

    pub fn from_simple_segments(
        kind: PathKind,
        segments: impl IntoIterator<Item = Name>,
    ) -> ModPath {
        let segments = segments.into_iter().collect::<Vec<_>>();
        ModPath { kind, segments }
    }

    pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> ModPath {
        name_ref.as_name().into()
    }

    /// Converts an `tt::Ident` into a single-identifier `Path`.
    pub(crate) fn from_tt_ident(ident: &tt::Ident) -> ModPath {
        ident.as_name().into()
    }

    /// Calls `cb` with all paths, represented by this use item.
    pub(crate) fn expand_use_item(
        item_src: InFile<ast::UseItem>,
        hygiene: &Hygiene,
        mut cb: impl FnMut(ModPath, &ast::UseTree, /* is_glob */ bool, Option<Name>),
    ) {
        if let Some(tree) = item_src.value.use_tree() {
            lower::lower_use_tree(None, tree, hygiene, &mut cb);
        }
    }

    pub fn is_ident(&self) -> bool {
        self.kind == PathKind::Plain && self.segments.len() == 1
    }

    pub fn is_self(&self) -> bool {
        self.kind == PathKind::Super(0) && self.segments.is_empty()
    }

    /// If this path is a single identifier, like `foo`, return its name.
    pub fn as_ident(&self) -> Option<&Name> {
        if self.kind != PathKind::Plain || self.segments.len() > 1 {
            return None;
        }
        self.segments.first()
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Path {
    /// Type based path like `<T>::foo`.
    /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`.
    type_anchor: Option<Box<TypeRef>>,
    mod_path: ModPath,
    /// Invariant: the same len as self.path.segments
    generic_args: Vec<Option<Arc<GenericArgs>>>,
}

/// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This
/// also includes bindings of associated types, like in `Iterator<Item = Foo>`.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct GenericArgs {
    pub args: Vec<GenericArg>,
    /// This specifies whether the args contain a Self type as the first
    /// element. This is the case for path segments like `<T as Trait>`, where
    /// `T` is actually a type parameter for the path `Trait` specifying the
    /// Self type. Otherwise, when we have a path `Trait<X, Y>`, the Self type
    /// is left out.
    pub has_self_type: bool,
    /// Associated type bindings like in `Iterator<Item = T>`.
    pub bindings: Vec<(Name, TypeRef)>,
}

/// A single generic argument.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum GenericArg {
    Type(TypeRef),
    // or lifetime...
}

impl Path {
    /// Converts an `ast::Path` to `Path`. Works with use trees.
    /// DEPRECATED: It does not handle `$crate` from macro call.
    pub fn from_ast(path: ast::Path) -> Option<Path> {
        lower::lower_path(path, &Hygiene::new_unhygienic())
    }

    /// Converts an `ast::Path` to `Path`. Works with use trees.
    /// It correctly handles `$crate` based path from macro call.
    pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
        lower::lower_path(path, hygiene)
    }

    /// Converts an `ast::NameRef` into a single-identifier `Path`.
    pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path {
        Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] }
    }

    pub fn kind(&self) -> &PathKind {
        &self.mod_path.kind
    }

    pub fn type_anchor(&self) -> Option<&TypeRef> {
        self.type_anchor.as_ref().map(|it| &**it)
    }

    pub fn segments(&self) -> PathSegments<'_> {
        PathSegments {
            segments: self.mod_path.segments.as_slice(),
            generic_args: self.generic_args.as_slice(),
        }
    }

    pub fn mod_path(&self) -> &ModPath {
        &self.mod_path
    }

    pub fn qualifier(&self) -> Option<Path> {
        if self.mod_path.is_ident() {
            return None;
        }
        let res = Path {
            type_anchor: self.type_anchor.clone(),
            mod_path: ModPath {
                kind: self.mod_path.kind.clone(),
                segments: self.mod_path.segments[..self.mod_path.segments.len() - 1].to_vec(),
            },
            generic_args: self.generic_args[..self.generic_args.len() - 1].to_vec(),
        };
        Some(res)
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PathSegment<'a> {
    pub name: &'a Name,
    pub args_and_bindings: Option<&'a GenericArgs>,
}

pub struct PathSegments<'a> {
    segments: &'a [Name],
    generic_args: &'a [Option<Arc<GenericArgs>>],
}

impl<'a> PathSegments<'a> {
    pub const EMPTY: PathSegments<'static> = PathSegments { segments: &[], generic_args: &[] };
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
    pub fn len(&self) -> usize {
        self.segments.len()
    }
    pub fn first(&self) -> Option<PathSegment<'a>> {
        self.get(0)
    }
    pub fn last(&self) -> Option<PathSegment<'a>> {
        self.get(self.len().checked_sub(1)?)
    }
    pub fn get(&self, idx: usize) -> Option<PathSegment<'a>> {
        assert_eq!(self.segments.len(), self.generic_args.len());
        let res = PathSegment {
            name: self.segments.get(idx)?,
            args_and_bindings: self.generic_args.get(idx).unwrap().as_ref().map(|it| &**it),
        };
        Some(res)
    }
    pub fn skip(&self, len: usize) -> PathSegments<'a> {
        assert_eq!(self.segments.len(), self.generic_args.len());
        PathSegments { segments: &self.segments[len..], generic_args: &self.generic_args[len..] }
    }
    pub fn take(&self, len: usize) -> PathSegments<'a> {
        assert_eq!(self.segments.len(), self.generic_args.len());
        PathSegments { segments: &self.segments[..len], generic_args: &self.generic_args[..len] }
    }
    pub fn iter(&self) -> impl Iterator<Item = PathSegment<'a>> {
        self.segments.iter().zip(self.generic_args.iter()).map(|(name, args)| PathSegment {
            name,
            args_and_bindings: args.as_ref().map(|it| &**it),
        })
    }
}

impl GenericArgs {
    pub(crate) fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> {
        lower::lower_generic_args(node)
    }

    pub(crate) fn empty() -> GenericArgs {
        GenericArgs { args: Vec::new(), has_self_type: false, bindings: Vec::new() }
    }
}

impl From<Name> for Path {
    fn from(name: Name) -> Path {
        Path {
            type_anchor: None,
            mod_path: ModPath::from_simple_segments(PathKind::Plain, iter::once(name)),
            generic_args: vec![None],
        }
    }
}

impl From<Name> for ModPath {
    fn from(name: Name) -> ModPath {
        ModPath::from_simple_segments(PathKind::Plain, iter::once(name))
    }
}

pub use hir_expand::name as __name;

#[macro_export]
macro_rules! __known_path {
    (std::iter::IntoIterator) => {};
    (std::result::Result) => {};
    (std::ops::Range) => {};
    (std::ops::RangeFrom) => {};
    (std::ops::RangeFull) => {};
    (std::ops::RangeTo) => {};
    (std::ops::RangeToInclusive) => {};
    (std::ops::RangeInclusive) => {};
    (std::boxed::Box) => {};
    (std::future::Future) => {};
    (std::ops::Try) => {};
    (std::ops::Neg) => {};
    (std::ops::Not) => {};
    (std::ops::Index) => {};
    ($path:path) => {
        compile_error!("Please register your known path in the path module")
    };
}

#[macro_export]
macro_rules! __path {
    ($start:ident $(:: $seg:ident)*) => ({
        $crate::__known_path!($start $(:: $seg)*);
        $crate::path::ModPath::from_simple_segments($crate::path::PathKind::Abs, vec![
            $crate::path::__name![$start], $($crate::path::__name![$seg],)*
        ])
    });
}

pub use crate::__path as path;
<commit_msg>Simplify<commit_after>//! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`.
mod lower;

use std::{iter, sync::Arc};

use hir_expand::{
    hygiene::Hygiene,
    name::{AsName, Name},
};
use ra_db::CrateId;
use ra_syntax::ast;

use crate::{type_ref::TypeRef, InFile};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ModPath {
    pub kind: PathKind,
    pub segments: Vec<Name>,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum PathKind {
    Plain,
    /// `self::` is `Super(0)`
    Super(u8),
    Crate,
    /// Absolute path (::foo)
    Abs,
    /// `$crate` from macro expansion
    DollarCrate(CrateId),
}

impl ModPath {
    pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> {
        lower::lower_path(path, hygiene).map(|it| it.mod_path)
    }

    pub fn from_simple_segments(
        kind: PathKind,
        segments: impl IntoIterator<Item = Name>,
    ) -> ModPath {
        let segments = segments.into_iter().collect::<Vec<_>>();
        ModPath { kind, segments }
    }

    pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> ModPath {
        name_ref.as_name().into()
    }

    /// Converts an `tt::Ident` into a single-identifier `Path`.
    pub(crate) fn from_tt_ident(ident: &tt::Ident) -> ModPath {
        ident.as_name().into()
    }

    /// Calls `cb` with all paths, represented by this use item.
    pub(crate) fn expand_use_item(
        item_src: InFile<ast::UseItem>,
        hygiene: &Hygiene,
        mut cb: impl FnMut(ModPath, &ast::UseTree, /* is_glob */ bool, Option<Name>),
    ) {
        if let Some(tree) = item_src.value.use_tree() {
            lower::lower_use_tree(None, tree, hygiene, &mut cb);
        }
    }

    pub fn is_ident(&self) -> bool {
        self.kind == PathKind::Plain && self.segments.len() == 1
    }

    pub fn is_self(&self) -> bool {
        self.kind == PathKind::Super(0) && self.segments.is_empty()
    }

    /// If this path is a single identifier, like `foo`, return its name.
    pub fn as_ident(&self) -> Option<&Name> {
        if self.kind != PathKind::Plain || self.segments.len() > 1 {
            return None;
        }
        self.segments.first()
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Path {
    /// Type based path like `<T>::foo`.
    /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`.
    type_anchor: Option<Box<TypeRef>>,
    mod_path: ModPath,
    /// Invariant: the same len as self.path.segments
    generic_args: Vec<Option<Arc<GenericArgs>>>,
}

/// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This
/// also includes bindings of associated types, like in `Iterator<Item = Foo>`.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct GenericArgs {
    pub args: Vec<GenericArg>,
    /// This specifies whether the args contain a Self type as the first
    /// element. This is the case for path segments like `<T as Trait>`, where
    /// `T` is actually a type parameter for the path `Trait` specifying the
    /// Self type. Otherwise, when we have a path `Trait<X, Y>`, the Self type
    /// is left out.
    pub has_self_type: bool,
    /// Associated type bindings like in `Iterator<Item = T>`.
    pub bindings: Vec<(Name, TypeRef)>,
}

/// A single generic argument.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum GenericArg {
    Type(TypeRef),
    // or lifetime...
}

impl Path {
    /// Converts an `ast::Path` to `Path`. Works with use trees.
    /// DEPRECATED: It does not handle `$crate` from macro call.
    pub fn from_ast(path: ast::Path) -> Option<Path> {
        lower::lower_path(path, &Hygiene::new_unhygienic())
    }

    /// Converts an `ast::Path` to `Path`. Works with use trees.
    /// It correctly handles `$crate` based path from macro call.
    pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
        lower::lower_path(path, hygiene)
    }

    /// Converts an `ast::NameRef` into a single-identifier `Path`.
    pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path {
        Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] }
    }

    pub fn kind(&self) -> &PathKind {
        &self.mod_path.kind
    }

    pub fn type_anchor(&self) -> Option<&TypeRef> {
        self.type_anchor.as_deref()
    }

    pub fn segments(&self) -> PathSegments<'_> {
        PathSegments {
            segments: self.mod_path.segments.as_slice(),
            generic_args: self.generic_args.as_slice(),
        }
    }

    pub fn mod_path(&self) -> &ModPath {
        &self.mod_path
    }

    pub fn qualifier(&self) -> Option<Path> {
        if self.mod_path.is_ident() {
            return None;
        }
        let res = Path {
            type_anchor: self.type_anchor.clone(),
            mod_path: ModPath {
                kind: self.mod_path.kind.clone(),
                segments: self.mod_path.segments[..self.mod_path.segments.len() - 1].to_vec(),
            },
            generic_args: self.generic_args[..self.generic_args.len() - 1].to_vec(),
        };
        Some(res)
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PathSegment<'a> {
    pub name: &'a Name,
    pub args_and_bindings: Option<&'a GenericArgs>,
}

pub struct PathSegments<'a> {
    segments: &'a [Name],
    generic_args: &'a [Option<Arc<GenericArgs>>],
}

impl<'a> PathSegments<'a> {
    pub const EMPTY: PathSegments<'static> = PathSegments { segments: &[], generic_args: &[] };
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
    pub fn len(&self) -> usize {
        self.segments.len()
    }
    pub fn first(&self) -> Option<PathSegment<'a>> {
        self.get(0)
    }
    pub fn last(&self) -> Option<PathSegment<'a>> {
        self.get(self.len().checked_sub(1)?)
    }
    pub fn get(&self, idx: usize) -> Option<PathSegment<'a>> {
        assert_eq!(self.segments.len(), self.generic_args.len());
        let res = PathSegment {
            name: self.segments.get(idx)?,
            args_and_bindings: self.generic_args.get(idx).unwrap().as_ref().map(|it| &**it),
        };
        Some(res)
    }
    pub fn skip(&self, len: usize) -> PathSegments<'a> {
        assert_eq!(self.segments.len(), self.generic_args.len());
        PathSegments { segments: &self.segments[len..], generic_args: &self.generic_args[len..] }
    }
    pub fn take(&self, len: usize) -> PathSegments<'a> {
        assert_eq!(self.segments.len(), self.generic_args.len());
        PathSegments { segments: &self.segments[..len], generic_args: &self.generic_args[..len] }
    }
    pub fn iter(&self) -> impl Iterator<Item = PathSegment<'a>> {
        self.segments.iter().zip(self.generic_args.iter()).map(|(name, args)| PathSegment {
            name,
            args_and_bindings: args.as_ref().map(|it| &**it),
        })
    }
}

impl GenericArgs {
    pub(crate) fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> {
        lower::lower_generic_args(node)
    }

    pub(crate) fn empty() -> GenericArgs {
        GenericArgs { args: Vec::new(), has_self_type: false, bindings: Vec::new() }
    }
}

impl From<Name> for Path {
    fn from(name: Name) -> Path {
        Path {
            type_anchor: None,
            mod_path: ModPath::from_simple_segments(PathKind::Plain, iter::once(name)),
            generic_args: vec![None],
        }
    }
}

impl From<Name> for ModPath {
    fn from(name: Name) -> ModPath {
        ModPath::from_simple_segments(PathKind::Plain, iter::once(name))
    }
}

pub use hir_expand::name as __name;

#[macro_export]
macro_rules! __known_path {
    (std::iter::IntoIterator) => {};
    (std::result::Result) => {};
    (std::ops::Range) => {};
    (std::ops::RangeFrom) => {};
    (std::ops::RangeFull) => {};
    (std::ops::RangeTo) => {};
    (std::ops::RangeToInclusive) => {};
    (std::ops::RangeInclusive) => {};
    (std::boxed::Box) => {};
    (std::future::Future) => {};
    (std::ops::Try) => {};
    (std::ops::Neg) => {};
    (std::ops::Not) => {};
    (std::ops::Index) => {};
    ($path:path) => {
        compile_error!("Please register your known path in the path module")
    };
}

#[macro_export]
macro_rules! __path {
    ($start:ident $(:: $seg:ident)*) => ({
        $crate::__known_path!($start $(:: $seg)*);
        $crate::path::ModPath::from_simple_segments($crate::path::PathKind::Abs, vec![
            $crate::path::__name![$start], $($crate::path::__name![$seg],)*
        ])
    });
}

pub use crate::__path as path;
<|endoftext|>


<commit_before><commit_msg>Don't create a terminal if the client doesn't support runInTerminal.<commit_after><|endoftext|>


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

//! Some lints that are built in to the compiler.
//!
//! These are the built-in lints that are emitted direct in the main
//! compiler code, rather than using their own custom pass. Those
//! lints are all available in `rustc_lint::builtin`.

use lint::{LintPass, LateLintPass, LintArray};

declare_lint! {
    pub CONST_ERR,
    Warn,
    "constant evaluation detected erroneous expression"
}

declare_lint! {
    pub UNUSED_IMPORTS,
    Warn,
    "imports that are never used"
}

declare_lint! {
    pub UNUSED_EXTERN_CRATES,
    Allow,
    "extern crates that are never used"
}

declare_lint! {
    pub UNUSED_QUALIFICATIONS,
    Allow,
    "detects unnecessarily qualified names"
}

declare_lint! {
    pub UNKNOWN_LINTS,
    Warn,
    "unrecognized lint attribute"
}

declare_lint! {
    pub UNUSED_VARIABLES,
    Warn,
    "detect variables which are not used in any way"
}

declare_lint! {
    pub UNUSED_ASSIGNMENTS,
    Warn,
    "detect assignments that will never be read"
}

declare_lint! {
    pub DEAD_CODE,
    Warn,
    "detect unused, unexported items"
}

declare_lint! {
    pub UNREACHABLE_CODE,
    Warn,
    "detects unreachable code paths"
}

declare_lint! {
    pub WARNINGS,
    Warn,
    "mass-change the level for lints which produce warnings"
}

declare_lint! {
    pub UNUSED_FEATURES,
    Warn,
    "unused or unknown features found in crate-level #[feature] directives"
}

declare_lint! {
    pub STABLE_FEATURES,
    Warn,
    "stable features found in #[feature] directive"
}

declare_lint! {
    pub UNKNOWN_CRATE_TYPES,
    Deny,
    "unknown crate type found in #[crate_type] directive"
}

declare_lint! {
    pub FAT_PTR_TRANSMUTES,
    Allow,
    "detects transmutes of fat pointers"
}

declare_lint! {
    pub TRIVIAL_CASTS,
    Allow,
    "detects trivial casts which could be removed"
}

declare_lint! {
    pub TRIVIAL_NUMERIC_CASTS,
    Allow,
    "detects trivial casts of numeric types which could be removed"
}

declare_lint! {
    pub PRIVATE_IN_PUBLIC,
    Warn,
    "detect private items in public interfaces not caught by the old implementation"
}

declare_lint! {
    pub INACCESSIBLE_EXTERN_CRATE,
    Deny,
    "use of inaccessible extern crate erroneously allowed"
}

declare_lint! {
    pub INVALID_TYPE_PARAM_DEFAULT,
    Deny,
    "type parameter default erroneously allowed in invalid location"
}

declare_lint! {
    pub ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN,
    Deny,
    "floating-point constants cannot be used in patterns"
}

declare_lint! {
    pub ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN,
    Deny,
    "constants of struct or enum type can only be used in a pattern if \
     the struct or enum has `#[derive(PartialEq, Eq)]`"
}

declare_lint! {
    pub RAW_POINTER_DERIVE,
    Warn,
    "uses of #[derive] with raw pointers are rarely correct"
}

declare_lint! {
    pub TRANSMUTE_FROM_FN_ITEM_TYPES,
    Deny,
    "transmute from function item type to pointer-sized type erroneously allowed"
}

declare_lint! {
    pub HR_LIFETIME_IN_ASSOC_TYPE,
    Warn,
    "binding for associated type references higher-ranked lifetime \
     that does not appear in the trait input types"
}

declare_lint! {
    pub OVERLAPPING_INHERENT_IMPLS,
    Deny,
    "two overlapping inherent impls define an item with the same name were erroneously allowed"
}

declare_lint! {
    pub RENAMED_AND_REMOVED_LINTS,
    Warn,
    "lints that have been renamed or removed"
}

declare_lint! {
    pub SUPER_OR_SELF_IN_GLOBAL_PATH,
    Deny,
    "detects super or self keywords at the beginning of global path"
}

declare_lint! {
    pub LIFETIME_UNDERSCORE,
    Deny,
    "lifetimes or labels named `'_` were erroneously allowed"
}

declare_lint! {
    pub SAFE_EXTERN_STATICS,
    Warn,
    "safe access to extern statics was erroneously allowed"
}

declare_lint! {
    pub PATTERNS_IN_FNS_WITHOUT_BODY,
    Warn,
    "patterns in functions without body were erroneously allowed"
}

declare_lint! {
    pub EXTRA_REQUIREMENT_IN_IMPL,
    Warn,
    "detects extra requirements in impls that were erroneously allowed"
}

declare_lint! {
    pub LEGACY_DIRECTORY_OWNERSHIP,
    Warn,
    "non-inline, non-`#[path]` modules (e.g. `mod foo;`) were erroneously allowed in some files \
     not named `mod.rs`"
}

/// Does nothing as a lint pass, but registers some `Lint`s
/// which are used by other parts of the compiler.
#[derive(Copy, Clone)]
pub struct HardwiredLints;

impl LintPass for HardwiredLints {
    fn get_lints(&self) -> LintArray {
        lint_array!(
            UNUSED_IMPORTS,
            UNUSED_EXTERN_CRATES,
            UNUSED_QUALIFICATIONS,
            UNKNOWN_LINTS,
            UNUSED_VARIABLES,
            UNUSED_ASSIGNMENTS,
            DEAD_CODE,
            UNREACHABLE_CODE,
            WARNINGS,
            UNUSED_FEATURES,
            STABLE_FEATURES,
            UNKNOWN_CRATE_TYPES,
            FAT_PTR_TRANSMUTES,
            TRIVIAL_CASTS,
            TRIVIAL_NUMERIC_CASTS,
            PRIVATE_IN_PUBLIC,
            INACCESSIBLE_EXTERN_CRATE,
            INVALID_TYPE_PARAM_DEFAULT,
            ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN,
            ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN,
            CONST_ERR,
            RAW_POINTER_DERIVE,
            TRANSMUTE_FROM_FN_ITEM_TYPES,
            OVERLAPPING_INHERENT_IMPLS,
            RENAMED_AND_REMOVED_LINTS,
            SUPER_OR_SELF_IN_GLOBAL_PATH,
            HR_LIFETIME_IN_ASSOC_TYPE,
            LIFETIME_UNDERSCORE,
            SAFE_EXTERN_STATICS,
            PATTERNS_IN_FNS_WITHOUT_BODY,
            EXTRA_REQUIREMENT_IN_IMPL,
            LEGACY_DIRECTORY_OWNERSHIP
        )
    }
}

impl LateLintPass for HardwiredLints {}
<commit_msg>Auto merge of #37843 - nikomatsakis:issue-33685-hard-error, r=eddyb<commit_after>// Copyright 2012-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.

//! Some lints that are built in to the compiler.
//!
//! These are the built-in lints that are emitted direct in the main
//! compiler code, rather than using their own custom pass. Those
//! lints are all available in `rustc_lint::builtin`.

use lint::{LintPass, LateLintPass, LintArray};

declare_lint! {
    pub CONST_ERR,
    Warn,
    "constant evaluation detected erroneous expression"
}

declare_lint! {
    pub UNUSED_IMPORTS,
    Warn,
    "imports that are never used"
}

declare_lint! {
    pub UNUSED_EXTERN_CRATES,
    Allow,
    "extern crates that are never used"
}

declare_lint! {
    pub UNUSED_QUALIFICATIONS,
    Allow,
    "detects unnecessarily qualified names"
}

declare_lint! {
    pub UNKNOWN_LINTS,
    Warn,
    "unrecognized lint attribute"
}

declare_lint! {
    pub UNUSED_VARIABLES,
    Warn,
    "detect variables which are not used in any way"
}

declare_lint! {
    pub UNUSED_ASSIGNMENTS,
    Warn,
    "detect assignments that will never be read"
}

declare_lint! {
    pub DEAD_CODE,
    Warn,
    "detect unused, unexported items"
}

declare_lint! {
    pub UNREACHABLE_CODE,
    Warn,
    "detects unreachable code paths"
}

declare_lint! {
    pub WARNINGS,
    Warn,
    "mass-change the level for lints which produce warnings"
}

declare_lint! {
    pub UNUSED_FEATURES,
    Warn,
    "unused or unknown features found in crate-level #[feature] directives"
}

declare_lint! {
    pub STABLE_FEATURES,
    Warn,
    "stable features found in #[feature] directive"
}

declare_lint! {
    pub UNKNOWN_CRATE_TYPES,
    Deny,
    "unknown crate type found in #[crate_type] directive"
}

declare_lint! {
    pub FAT_PTR_TRANSMUTES,
    Allow,
    "detects transmutes of fat pointers"
}

declare_lint! {
    pub TRIVIAL_CASTS,
    Allow,
    "detects trivial casts which could be removed"
}

declare_lint! {
    pub TRIVIAL_NUMERIC_CASTS,
    Allow,
    "detects trivial casts of numeric types which could be removed"
}

declare_lint! {
    pub PRIVATE_IN_PUBLIC,
    Warn,
    "detect private items in public interfaces not caught by the old implementation"
}

declare_lint! {
    pub INACCESSIBLE_EXTERN_CRATE,
    Deny,
    "use of inaccessible extern crate erroneously allowed"
}

declare_lint! {
    pub INVALID_TYPE_PARAM_DEFAULT,
    Deny,
    "type parameter default erroneously allowed in invalid location"
}

declare_lint! {
    pub ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN,
    Deny,
    "floating-point constants cannot be used in patterns"
}

declare_lint! {
    pub ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN,
    Deny,
    "constants of struct or enum type can only be used in a pattern if \
     the struct or enum has `#[derive(PartialEq, Eq)]`"
}

declare_lint! {
    pub RAW_POINTER_DERIVE,
    Warn,
    "uses of #[derive] with raw pointers are rarely correct"
}

declare_lint! {
    pub TRANSMUTE_FROM_FN_ITEM_TYPES,
    Deny,
    "transmute from function item type to pointer-sized type erroneously allowed"
}

declare_lint! {
    pub HR_LIFETIME_IN_ASSOC_TYPE,
    Deny,
    "binding for associated type references higher-ranked lifetime \
     that does not appear in the trait input types"
}

declare_lint! {
    pub OVERLAPPING_INHERENT_IMPLS,
    Deny,
    "two overlapping inherent impls define an item with the same name were erroneously allowed"
}

declare_lint! {
    pub RENAMED_AND_REMOVED_LINTS,
    Warn,
    "lints that have been renamed or removed"
}

declare_lint! {
    pub SUPER_OR_SELF_IN_GLOBAL_PATH,
    Deny,
    "detects super or self keywords at the beginning of global path"
}

declare_lint! {
    pub LIFETIME_UNDERSCORE,
    Deny,
    "lifetimes or labels named `'_` were erroneously allowed"
}

declare_lint! {
    pub SAFE_EXTERN_STATICS,
    Warn,
    "safe access to extern statics was erroneously allowed"
}

declare_lint! {
    pub PATTERNS_IN_FNS_WITHOUT_BODY,
    Warn,
    "patterns in functions without body were erroneously allowed"
}

declare_lint! {
    pub EXTRA_REQUIREMENT_IN_IMPL,
    Warn,
    "detects extra requirements in impls that were erroneously allowed"
}

declare_lint! {
    pub LEGACY_DIRECTORY_OWNERSHIP,
    Warn,
    "non-inline, non-`#[path]` modules (e.g. `mod foo;`) were erroneously allowed in some files \
     not named `mod.rs`"
}

/// Does nothing as a lint pass, but registers some `Lint`s
/// which are used by other parts of the compiler.
#[derive(Copy, Clone)]
pub struct HardwiredLints;

impl LintPass for HardwiredLints {
    fn get_lints(&self) -> LintArray {
        lint_array!(
            UNUSED_IMPORTS,
            UNUSED_EXTERN_CRATES,
            UNUSED_QUALIFICATIONS,
            UNKNOWN_LINTS,
            UNUSED_VARIABLES,
            UNUSED_ASSIGNMENTS,
            DEAD_CODE,
            UNREACHABLE_CODE,
            WARNINGS,
            UNUSED_FEATURES,
            STABLE_FEATURES,
            UNKNOWN_CRATE_TYPES,
            FAT_PTR_TRANSMUTES,
            TRIVIAL_CASTS,
            TRIVIAL_NUMERIC_CASTS,
            PRIVATE_IN_PUBLIC,
            INACCESSIBLE_EXTERN_CRATE,
            INVALID_TYPE_PARAM_DEFAULT,
            ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN,
            ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN,
            CONST_ERR,
            RAW_POINTER_DERIVE,
            TRANSMUTE_FROM_FN_ITEM_TYPES,
            OVERLAPPING_INHERENT_IMPLS,
            RENAMED_AND_REMOVED_LINTS,
            SUPER_OR_SELF_IN_GLOBAL_PATH,
            HR_LIFETIME_IN_ASSOC_TYPE,
            LIFETIME_UNDERSCORE,
            SAFE_EXTERN_STATICS,
            PATTERNS_IN_FNS_WITHOUT_BODY,
            EXTRA_REQUIREMENT_IN_IMPL,
            LEGACY_DIRECTORY_OWNERSHIP
        )
    }
}

impl LateLintPass for HardwiredLints {}
<|endoftext|>


<commit_before>use Context::*;

use rustc_errors::{struct_span_err, Applicability};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::{Destination, Movability, Node};
use rustc_middle::hir::map::Map;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::Span;

#[derive(Clone, Copy, Debug, PartialEq)]
enum Context {
    Normal,
    Loop(hir::LoopSource),
    Closure(Span),
    AsyncClosure(Span),
    LabeledBlock,
    AnonConst,
}

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

fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: DefId) {
    tcx.hir().visit_item_likes_in_module(
        module_def_id,
        &mut CheckLoopVisitor { sess: &tcx.sess, hir_map: tcx.hir(), cx: Normal }.as_deep_visitor(),
    );
}

pub(crate) fn provide(providers: &mut Providers<'_>) {
    *providers = Providers { check_mod_loops, ..*providers };
}

impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
    type Map = Map<'hir>;

    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::OnlyBodies(self.hir_map)
    }

    fn visit_anon_const(&mut self, c: &'hir hir::AnonConst) {
        self.with_context(AnonConst, |v| intravisit::walk_anon_const(v, c));
    }

    fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
        match e.kind {
            hir::ExprKind::Loop(ref b, _, source) => {
                self.with_context(Loop(source), |v| v.visit_block(&b));
            }
            hir::ExprKind::Closure(_, ref function_decl, b, span, movability) => {
                let cx = if let Some(Movability::Static) = movability {
                    AsyncClosure(span)
                } else {
                    Closure(span)
                };
                self.visit_fn_decl(&function_decl);
                self.with_context(cx, |v| v.visit_nested_body(b));
            }
            hir::ExprKind::Block(ref b, Some(_label)) => {
                self.with_context(LabeledBlock, |v| v.visit_block(&b));
            }
            hir::ExprKind::Break(label, ref opt_expr) => {
                opt_expr.as_ref().map(|e| self.visit_expr(e));

                if self.require_label_in_labeled_block(e.span, &label, "break") {
                    // If we emitted an error about an unlabeled break in a labeled
                    // block, we don't need any further checking for this break any more
                    return;
                }

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

                if loop_id != hir::DUMMY_HIR_ID {
                    if let Node::Block(_) = self.hir_map.find(loop_id).unwrap() {
                        return;
                    }
                }

                if opt_expr.is_some() {
                    let loop_kind = if loop_id == hir::DUMMY_HIR_ID {
                        None
                    } else {
                        Some(match self.hir_map.expect_expr(loop_id).kind {
                            hir::ExprKind::Loop(_, _, source) => source,
                            ref r => {
                                span_bug!(e.span, "break label resolved to a non-loop: {:?}", r)
                            }
                        })
                    };
                    match loop_kind {
                        None | Some(hir::LoopSource::Loop) => (),
                        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(),
                                Applicability::MaybeIncorrect,
                            )
                            .emit();
                        }
                    }
                }

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

                match destination.target_id {
                    Ok(loop_id) => {
                        if let Node::Block(block) = self.hir_map.find(loop_id).unwrap() {
                            struct_span_err!(
                                self.sess,
                                e.span,
                                E0696,
                                "`continue` pointing to a labeled block"
                            )
                            .span_label(e.span, "labeled blocks cannot be `continue`'d")
                            .span_label(block.span, "labeled block the `continue` points to")
                            .emit();
                        }
                    }
                    Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
                        self.emit_unlabled_cf_in_while_condition(e.span, "continue");
                    }
                    Err(_) => {}
                }
                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) {
        let err_inside_of = |article, ty, closure_span| {
            struct_span_err!(self.sess, span, E0267, "`{}` inside of {} {}", name, article, ty)
                .span_label(span, format!("cannot `{}` inside of {} {}", name, article, ty))
                .span_label(closure_span, &format!("enclosing {}", ty))
                .emit();
        };

        match self.cx {
            LabeledBlock | Loop(_) => {}
            Closure(closure_span) => err_inside_of("a", "closure", closure_span),
            AsyncClosure(closure_span) => err_inside_of("an", "`async` block", closure_span),
            Normal | AnonConst => {
                struct_span_err!(self.sess, span, E0268, "`{}` outside of a loop", name)
                    .span_label(span, format!("cannot `{}` outside of a loop", name))
                    .emit();
            }
        }
    }

    fn require_label_in_labeled_block(
        &mut self,
        span: Span,
        label: &Destination,
        cf_type: &str,
    ) -> bool {
        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();
                return true;
            }
        }
        false
    }
    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>Remove usage of `DUMMY_HIR_ID` in `CheckLoopVisitor`<commit_after>use Context::*;

use rustc_errors::{struct_span_err, Applicability};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::{Destination, Movability, Node};
use rustc_middle::hir::map::Map;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::Span;

#[derive(Clone, Copy, Debug, PartialEq)]
enum Context {
    Normal,
    Loop(hir::LoopSource),
    Closure(Span),
    AsyncClosure(Span),
    LabeledBlock,
    AnonConst,
}

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

fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: DefId) {
    tcx.hir().visit_item_likes_in_module(
        module_def_id,
        &mut CheckLoopVisitor { sess: &tcx.sess, hir_map: tcx.hir(), cx: Normal }.as_deep_visitor(),
    );
}

pub(crate) fn provide(providers: &mut Providers<'_>) {
    *providers = Providers { check_mod_loops, ..*providers };
}

impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
    type Map = Map<'hir>;

    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::OnlyBodies(self.hir_map)
    }

    fn visit_anon_const(&mut self, c: &'hir hir::AnonConst) {
        self.with_context(AnonConst, |v| intravisit::walk_anon_const(v, c));
    }

    fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
        match e.kind {
            hir::ExprKind::Loop(ref b, _, source) => {
                self.with_context(Loop(source), |v| v.visit_block(&b));
            }
            hir::ExprKind::Closure(_, ref function_decl, b, span, movability) => {
                let cx = if let Some(Movability::Static) = movability {
                    AsyncClosure(span)
                } else {
                    Closure(span)
                };
                self.visit_fn_decl(&function_decl);
                self.with_context(cx, |v| v.visit_nested_body(b));
            }
            hir::ExprKind::Block(ref b, Some(_label)) => {
                self.with_context(LabeledBlock, |v| v.visit_block(&b));
            }
            hir::ExprKind::Break(label, ref opt_expr) => {
                opt_expr.as_ref().map(|e| self.visit_expr(e));

                if self.require_label_in_labeled_block(e.span, &label, "break") {
                    // If we emitted an error about an unlabeled break in a labeled
                    // block, we don't need any further checking for this break any more
                    return;
                }

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

                if let Some(loop_id) = loop_id {
                    if let Node::Block(_) = self.hir_map.find(loop_id).unwrap() {
                        return;
                    }
                }

                if opt_expr.is_some() {
                    let loop_kind = if let Some(loop_id) = loop_id {
                        Some(match self.hir_map.expect_expr(loop_id).kind {
                            hir::ExprKind::Loop(_, _, source) => source,
                            ref r => {
                                span_bug!(e.span, "break label resolved to a non-loop: {:?}", r)
                            }
                        })
                    } else {
                        None
                    };
                    match loop_kind {
                        None | Some(hir::LoopSource::Loop) => (),
                        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(),
                                Applicability::MaybeIncorrect,
                            )
                            .emit();
                        }
                    }
                }

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

                match destination.target_id {
                    Ok(loop_id) => {
                        if let Node::Block(block) = self.hir_map.find(loop_id).unwrap() {
                            struct_span_err!(
                                self.sess,
                                e.span,
                                E0696,
                                "`continue` pointing to a labeled block"
                            )
                            .span_label(e.span, "labeled blocks cannot be `continue`'d")
                            .span_label(block.span, "labeled block the `continue` points to")
                            .emit();
                        }
                    }
                    Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
                        self.emit_unlabled_cf_in_while_condition(e.span, "continue");
                    }
                    Err(_) => {}
                }
                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) {
        let err_inside_of = |article, ty, closure_span| {
            struct_span_err!(self.sess, span, E0267, "`{}` inside of {} {}", name, article, ty)
                .span_label(span, format!("cannot `{}` inside of {} {}", name, article, ty))
                .span_label(closure_span, &format!("enclosing {}", ty))
                .emit();
        };

        match self.cx {
            LabeledBlock | Loop(_) => {}
            Closure(closure_span) => err_inside_of("a", "closure", closure_span),
            AsyncClosure(closure_span) => err_inside_of("an", "`async` block", closure_span),
            Normal | AnonConst => {
                struct_span_err!(self.sess, span, E0268, "`{}` outside of a loop", name)
                    .span_label(span, format!("cannot `{}` outside of a loop", name))
                    .emit();
            }
        }
    }

    fn require_label_in_labeled_block(
        &mut self,
        span: Span,
        label: &Destination,
        cf_type: &str,
    ) -> bool {
        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();
                return true;
            }
        }
        false
    }
    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|>


<commit_before>struct NFA
{
	states: ~[State],
}

impl NFA
{
	pub fn new()	->	NFA
	{
		NFA { states: ~[] }
	}

	pub fn add_state(&mut self, state: State)
	{
		self.states.push(state);
	}

	pub fn link_states(&mut self, id0: int, id1: int)
	{
		self.states[id0].add_transition(id1);
	}

	pub fn print(&self)
	{
		println("\nprinting states:");
		for i in range(0, self.states.len())
		{
			print(fmt!("%u: ", i));
			self.states[i].print();
		}
		println("");
	}

	pub fn pop(&mut self)	->	State
	{
		self.states.pop()
	}

	pub fn len(&self)	->	int
	{
		self.states.len() as int
	}

	pub fn check(&self, string: ~str, c: ~[int])		->	bool
	{
		let mut curr = c.clone();
		//println(fmt!("check: string=%? c=%?", string, c));
		if string.len() > 0
		{
			let c = string.char_at(0);
			let mut next = ~[];
			// look to see if any current states have c or an
			// epsilon transition as a value
			let mut l = curr.len();
			let mut i = 0;
			while i < l
			{
				//println(fmt!("on character %?, state=%? val=%?", c, curr[i], self.states[curr[i]].val));
				if self.states[curr[i]].val == c
				{
					for j in range(0, self.states[curr[i]].transitions.len())
					{
						//println(fmt!("adding %d", self.states[curr[i]].transitions[j]));
						next.push(self.states[curr[i]].transitions[j]);
					}
				}
				else if self.states[curr[i]].val == '%'
				{
					for j in range(0, self.states[curr[i]].transitions.len())
					{
						//println(fmt!("pushing %d", self.states[curr[i]].transitions[j]));
						curr.push(self.states[curr[i]].transitions[j]);
						l += 1;
					}
				}
				i += 1;
				//println(fmt!("curr=%? next=%? l=%? i=%?", curr,next,l, i));
			}
			if next.len() == 0 { return false; }
			return self.check(string.slice_from(1).to_owned(), next);
		}
		else
		{
			// see if we're in a matching state
			for i in range(0, curr.len())
			{
				if self.states[curr[i]].accept
				{
					return true;
				}
			}
			// check to see if there are any epsilon transitions we
			// can make
			let mut next = ~[];
			for i in range(0, curr.len())
			{
				if self.states[curr[i]].val == '%'
				{
					for j in range(0, self.states[curr[i]].transitions.len())
					{
						next.push(self.states[curr[i]].transitions[j]);
					}
				}
			}
			//println(fmt!("curr=%? next=%?", curr, next));
			if next.len() > 0
			{
				return self.check(string, next);
			}
			return false;
		}
	}
}

#[deriving(Clone,DeepClone, Eq)]
struct State
{
	val: char,
	accept: bool,
	transitions: ~[int]
}

impl State
{
	pub fn new(c: char, b: bool)	->	State
	{
		State { val: c, accept: b, transitions: ~[] }
	}

	pub fn print(&self)
	{
		print(fmt!("value=%? matching=%? transitions={", self.val, self.accept));
		for i in range(0, self.transitions.len())
		{
			print(fmt!("%?,", self.transitions[i]));
		}
		println("}");
	}

	pub fn is_accept(&mut self, b: bool)
	{
		self.accept = b;
	}

	pub fn add_transition(&mut self, id: int)
	{
		self.transitions.push(id);
	}

	pub fn change_val(&mut self, c: char)
	{
		self.val = c;
	}
}

fn main()
{
	let test = "abb*";
	let strings = ~[~"a", ~"b", ~"aa", ~"bb", ~"ab", ~"ba", ~"aab", ~"aba", ~"baa", ~"abb", ~"bab", ~"bba", ~"bbb", ~"aaa"];
	let mut nfa = NFA::new();
	let head_state = State::new('%', false);
	nfa.add_state(head_state);
	let mut j = 0;
	for i in range(1,(test.len()+1) as int)
	{
		let c = test.char_at((i-1) as uint);
		match c
		{
			'*'	=>	{
						// prev state j
						// state_in
						// state_curr
						// state_out
						let mut state_in = nfa.pop();
						j -= 1;
						let c = state_in.val;
						let state_curr = State::new(c, false);
						state_in.change_val('%');
						let state_out = State::new('%', false);

						// don't need to link
						nfa.add_state(state_in);
						j += 1;
						// prev state
						// state_in j
						// state_curr
						// state_out

						// link to state_in
						nfa.add_state(state_curr);
						j += 1;
						// prev state
						// state_in
						// state_curr j
						// state_out
						nfa.link_states(j-1, j);

						// link to state_curr
						nfa.add_state(state_out);
						j += 1;
						// prev state
						// state_in
						// state_curr
						// state_out j
						nfa.link_states(j-1, j);

						// link prev state to state_out
						nfa.link_states(j-3, j);

						// link state_out to state_in,
						// since it's a *
						nfa.link_states(j, j-2);
					}
			'?'	=>	{
						let mut state_in = nfa.pop();
						j -= 1;
						let c = state_in.val;
						let state_curr = State::new(c, false);
						state_in.change_val('%');
						let state_out = State::new('%', false);

						// don't need to link
						nfa.add_state(state_in);
						j += 1;

						// link to state_in
						nfa.add_state(state_curr);
						j += 1;
						nfa.link_states(j-1, j);

						// link to state_curr
						nfa.add_state(state_out);
						j += 1;
						nfa.link_states(j-1, j);

						// link prev state to state_out
						nfa.link_states(j-3, j);

						// link state_in to state_out,
						// since it's a ?
						nfa.link_states(j-2, j);
					}
			_	=>	{
						let state = State::new(c, false);
						nfa.add_state(state);
						j += 1;
						// link with previous
						nfa.link_states(j-1, j);
					}
		};

		//println("");
		//nfa.print();
		//println("");
	}

	// add a tail state
	let tail_state = State::new('%', true);
	nfa.add_state(tail_state);
	// link with previous
	let l = nfa.len();
	nfa.link_states(l-2, l-1);

	nfa.print();

	let curr = ~[0];
	println(fmt!("Regex is: %s", test));
	for i in range(0, strings.len())
	{
		println(fmt!("%? %?", strings[i], nfa.check(strings[i].clone(), curr.clone())));
	}
}
<commit_msg>did '.'. looks like we'll need to name the char's options or some other more complex type...running into conflicts<commit_after>struct NFA
{
	states: ~[State],
}

impl NFA
{
	pub fn new()	->	NFA
	{
		NFA { states: ~[] }
	}

	pub fn add_state(&mut self, state: State)
	{
		self.states.push(state);
	}

	pub fn link_states(&mut self, id0: int, id1: int)
	{
		self.states[id0].add_transition(id1);
	}

	pub fn print(&self)
	{
		println("\nprinting states:");
		for i in range(0, self.states.len())
		{
			print(fmt!("%u: ", i));
			self.states[i].print();
		}
		println("");
	}

	pub fn pop(&mut self)	->	State
	{
		self.states.pop()
	}

	pub fn len(&self)	->	int
	{
		self.states.len() as int
	}

	pub fn check(&self, string: ~str, c: ~[int])		->	bool
	{
		let mut curr = c.clone();
		//println(fmt!("check: string=%? c=%?", string, c));
		if string.len() > 0
		{
			let c = string.char_at(0);
			let mut next = ~[];
			// look to see if any current states have c or an
			// epsilon transition as a value
			let mut l = curr.len();
			let mut i = 0;
			while i < l
			{
				//println(fmt!("on character %?, state=%? val=%?", c, curr[i], self.states[curr[i]].val));
				if self.states[curr[i]].val == c
				{
					for j in range(0, self.states[curr[i]].transitions.len())
					{
						//println(fmt!("adding %d", self.states[curr[i]].transitions[j]));
						next.push(self.states[curr[i]].transitions[j]);
					}
				}
				else if self.states[curr[i]].val == '.'
				{
					for j in range(0, self.states[curr[i]].transitions.len())
					{
						next.push(self.states[curr[i]].transitions[j]);
					}
				}
				else if self.states[curr[i]].val == '%'
				{
					for j in range(0, self.states[curr[i]].transitions.len())
					{
						//println(fmt!("pushing %d", self.states[curr[i]].transitions[j]));
						curr.push(self.states[curr[i]].transitions[j]);
						l += 1;
					}
				}
				i += 1;
				//println(fmt!("curr=%? next=%? l=%? i=%?", curr,next,l, i));
			}
			if next.len() == 0 { return false; }
			return self.check(string.slice_from(1).to_owned(), next);
		}
		else
		{
			// see if we're in a matching state
			for i in range(0, curr.len())
			{
				if self.states[curr[i]].accept
				{
					return true;
				}
			}
			// check to see if there are any epsilon transitions we
			// can make
			let mut next = ~[];
			for i in range(0, curr.len())
			{
				if self.states[curr[i]].val == '%'
				{
					for j in range(0, self.states[curr[i]].transitions.len())
					{
						next.push(self.states[curr[i]].transitions[j]);
					}
				}
			}
			//println(fmt!("curr=%? next=%?", curr, next));
			if next.len() > 0
			{
				return self.check(string, next);
			}
			return false;
		}
	}
}

#[deriving(Clone,DeepClone, Eq)]
struct State
{
	val: char,
	accept: bool,
	transitions: ~[int]
}

impl State
{
	pub fn new(c: char, b: bool)	->	State
	{
		State { val: c, accept: b, transitions: ~[] }
	}

	pub fn print(&self)
	{
		print(fmt!("value=%? matching=%? transitions={", self.val, self.accept));
		for i in range(0, self.transitions.len())
		{
			print(fmt!("%?,", self.transitions[i]));
		}
		println("}");
	}

	pub fn is_accept(&mut self, b: bool)
	{
		self.accept = b;
	}

	pub fn add_transition(&mut self, id: int)
	{
		self.transitions.push(id);
	}

	pub fn change_val(&mut self, c: char)
	{
		self.val = c;
	}
}

fn main()
{
	let test = "a.b";
	let strings = ~[~"a", ~"b", ~"aa", ~"bb", ~"ab", ~"ba", ~"aab", ~"aba", ~"baa", ~"abb", ~"bab", ~"bba", ~"bbb", ~"aaa", ~"abbb", ~"abba"];
	let mut nfa = NFA::new();
	let head_state = State::new('%', false);
	nfa.add_state(head_state);
	let mut j = 0;
	for i in range(1,(test.len()+1) as int)
	{
		let c = test.char_at((i-1) as uint);
		match c
		{
			'*'	=>	{
						// prev state j
						// state_in
						// state_curr
						// state_out
						let mut state_in = nfa.pop();
						j -= 1;
						let c = state_in.val;
						let state_curr = State::new(c, false);
						state_in.change_val('%');
						let state_out = State::new('%', false);

						// don't need to link
						nfa.add_state(state_in);
						j += 1;
						// prev state
						// state_in j
						// state_curr
						// state_out

						// link to state_in
						nfa.add_state(state_curr);
						j += 1;
						// prev state
						// state_in
						// state_curr j
						// state_out
						nfa.link_states(j-1, j);

						// link to state_curr
						nfa.add_state(state_out);
						j += 1;
						// prev state
						// state_in
						// state_curr
						// state_out j
						nfa.link_states(j-1, j);

						// link prev state to state_out
						nfa.link_states(j-3, j);

						// link state_out to state_in,
						// since it's a *
						nfa.link_states(j, j-2);
					}
			'+'	=>	{
						let mut state_in = nfa.pop();
						j -= 1;
						let c = state_in.val;
						let state_curr = State::new(c, false);
						state_in.change_val('%');
						let state_out = State::new('%', false);

						// don't need to link
						nfa.add_state(state_in);
						j += 1;

						// link to state_in
						nfa.add_state(state_curr);
						j += 1;
						nfa.link_states(j-1, j);

						// link to state_curr
						nfa.add_state(state_out);
						j += 1;
						nfa.link_states(j-1, j);

						// link state_out to state_in
						nfa.link_states(j, j-2);
					}
			'?'	=>	{
						let mut state_in = nfa.pop();
						j -= 1;
						let c = state_in.val;
						let state_curr = State::new(c, false);
						state_in.change_val('%');
						let state_out = State::new('%', false);

						// don't need to link
						nfa.add_state(state_in);
						j += 1;

						// link to state_in
						nfa.add_state(state_curr);
						j += 1;
						nfa.link_states(j-1, j);

						// link to state_curr
						nfa.add_state(state_out);
						j += 1;
						nfa.link_states(j-1, j);

						// link prev state to state_out
						nfa.link_states(j-3, j);

						// link state_in to state_out,
						// since it's a ?
						nfa.link_states(j-2, j);
					}
			'.'	=>	{
						let state = State::new(c, false);
						nfa.add_state(state);
						j += 1;
						// link with previous
						nfa.link_states(j-1, j);
					}
			_	=>	{
						let state = State::new(c, false);
						nfa.add_state(state);
						j += 1;
						// link with previous
						nfa.link_states(j-1, j);
					}
		};

		//println("");
		//nfa.print();
		//println("");
	}

	// add a tail state
	let tail_state = State::new('%', true);
	nfa.add_state(tail_state);
	// link with previous
	let l = nfa.len();
	nfa.link_states(l-2, l-1);

	nfa.print();

	let curr = ~[0];
	println(fmt!("Regex is: %s", test));
	for i in range(0, strings.len())
	{
		println(fmt!("%? %?", strings[i], nfa.check(strings[i].clone(), curr.clone())));
	}
}
<|endoftext|>


<commit_before>#[link(name="rm", vers="1.0.0", author="Arcterus")];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern mod extra;

use std::os;
use std::io::{stdin,stderr,stdio,fs,buffered,io_error};
use extra::getopts::groups;

enum InteractiveMode {
    InteractiveNone,
    InteractiveOnce,
    InteractiveAlways
}

impl Eq for InteractiveMode {
    fn eq(&self, other: &InteractiveMode) -> bool {
        match (*self, *other) {
            (InteractiveNone, InteractiveNone) |
            (InteractiveOnce, InteractiveOnce) |
            (InteractiveAlways, InteractiveAlways) => true,
            _ => false
        }
    }

    fn ne(&self, other: &InteractiveMode) -> bool {
        !self.eq(other)
    }
}

fn main() {
    let args = os::args();
    let program = args[0].clone();

    // TODO: make getopts support -R in addition to -r
    let opts = ~[
        groups::optflag("f", "force", "ignore nonexistent files and arguments, never prompt"),
        groups::optflag("i", "", "prompt before every removal"),
        groups::optflag("I", "", "prompt once before removing more than three files, or when removing recursively.  Less intrusive than -i, while still giving some protection against most mistakes"),
        groups::optflagopt("", "interactive", "prompt according to WHEN: never, once (-I), or always (-i).  Without WHEN, prompts always", "WHEN"),
        groups::optflag("", "one-file-system", "when removing a hierarchy recursively, skip any directory that is on a file system different from that of the corresponding command line argument (NOT IMPLEMENTED)"),
        groups::optflag("", "no-preserve-root", "do not treat '/' specially"),
        groups::optflag("", "preserve-root", "do not remove '/' (default)"),
        groups::optflag("r", "recursive", "remove directories and their contents recursively"),
        groups::optflag("d", "dir", "remove empty directories"),
        groups::optflag("v", "verbose", "explain what is being done"),
        groups::optflag("h", "help", "display this help and exit"),
        groups::optflag("V", "version", "output version information and exit")
    ];
    let matches = match groups::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            writeln!(&mut stderr() as &mut Writer,
                     "{}", f.to_err_msg());
            os::set_exit_status(1);
            return
        }
    };
    if matches.opt_present("help") {
        println("rm 1.0.0");
        println("");
        println("Usage:");
        println!("  {0:s} [OPTION]... [FILE]...", program);
        println("");
        print(groups::usage("Remove (unlink) the FILE(s).", opts));
        println("");
        println("By default, rm does not remove directories.  Use the --recursive (-r)");
        println("option to remove each listed directory, too, along with all of its contents");
        println("");
        println("To remove a file whose name starts with a '-', for example '-foo',");
        println("use one of these commands:");
        println("rm -- -foo");
        println("");
        println("rm ./-foo");
        println("");
        println("Note that if you use rm to remove a file, it might be possible to recover");
        println("some of its contents, given sufficient expertise and/or time.  For greater");
        println("assurance that the contents are truly unrecoverable, consider using shred.");
    } else if matches.opt_present("version") {
        println("rm 1.0.0");
    } else if matches.free.is_empty() {
        writeln!(&mut stderr() as &mut Writer, "Missing an argument");
        writeln!(&mut stderr() as &mut Writer,
                 "For help, try '{0:s} --help'", program);
        os::set_exit_status(1);
    } else {
        let force = matches.opt_present("force");
        let interactive =
            if matches.opt_present("i") {
                InteractiveAlways
            } else if matches.opt_present("I") {
                InteractiveOnce
            } else if matches.opt_present("interactive") {
                match matches.opt_str("interactive").unwrap() {
                    ~"none" => InteractiveNone,
                    ~"once" => InteractiveOnce,
                    ~"always" => InteractiveAlways,
                    val => {
                        writeln!(&mut stderr() as &mut Writer,
                                 "Invalid argument to interactive ({})", val);
                        os::set_exit_status(1);
                        return
                    }
                }
            } else {
                InteractiveNone
            };
        let one_fs = matches.opt_present("one-file-system");
        let preserve_root = !matches.opt_present("no-preserve-root");
        let recursive = matches.opt_present("recursive");
        let dir = matches.opt_present("dir");
        let verbose = matches.opt_present("verbose");
        if interactive == InteractiveOnce && (recursive || matches.free.len() > 3) {
            let msg =
                if recursive {
                    "Remove all arguments recursively? "
                } else {
                    "Remove all arguments? "
                };
            if !prompt(msg) {
                return;
            }
        }
        remove(matches.free, force, interactive, one_fs, preserve_root,
               recursive, dir, verbose);
    }
}

// TODO: implement one-file-system
fn remove(files: &[~str], force: bool, interactive: InteractiveMode, one_fs: bool, preserve_root: bool, recursive: bool, dir: bool, verbose: bool) {
    for filename in files.iter() {
        let file = Path::new(filename.to_owned());
        if file.exists() {
            if file.is_dir() {
                if recursive && (*filename != ~"/" || !preserve_root) {
                    remove(fs::walk_dir(&file).map(|x| x.as_str().unwrap().to_owned()).to_owned_vec(), force, interactive, one_fs, preserve_root, recursive, dir, verbose);
                    remove_dir(&file, *filename, interactive, verbose);
                } else if dir && (*filename != ~"/" || !preserve_root) {
                    remove_dir(&file, *filename, interactive, verbose);
                } else {
                    if recursive {
                        writeln!(&mut stderr() as &mut Writer,
                                 "Could not remove directory '{}'",
                                 *filename);
                    } else {
                        writeln!(&mut stderr() as &mut Writer,
                                 "Could not remove directory '{}' (did you mean to pass '-r'?)",
                                 *filename);
                    }
                    os::set_exit_status(1);
                }
            } else {
                remove_file(&file, *filename, interactive, verbose);
            }
        } else if !force {
            writeln!(&mut stderr() as &mut Writer,
                     "No such file or directory '{}'", *filename);
            os::set_exit_status(1);
        }
    }
}

fn remove_dir(path: &Path, name: &str, interactive: InteractiveMode, verbose: bool) {
    let response =
        if interactive == InteractiveAlways {
            prompt_file(path, name)
        } else {
            true
        };
    if response {
        io_error::cond.trap(|_| {
            writeln!(&mut stderr() as &mut Writer,
                     "Could not remove directory '{}'", name);
            os::set_exit_status(1);
        }).inside(|| {
            fs::rmdir(path);
            if verbose {
                println!("Removed '{}'", name);
            }
        });
    }
}

fn remove_file(path: &Path, name: &str, interactive: InteractiveMode, verbose: bool) {
    let response =
        if interactive == InteractiveAlways {
            prompt_file(path, name)
        } else {
            true
        };
    if response {
        io_error::cond.trap(|_| {
            writeln!(&mut stderr() as &mut Writer,
                     "Could not remove file '{}'", name);
            os::set_exit_status(1);
        }).inside(|| {
            fs::unlink(path);
            if verbose {
                println!("Removed '{}'", name);
            }
        });
    }
}

fn prompt_file(path: &Path, name: &str) -> bool {
    if path.is_dir() {
        prompt(format!("Remove directory '{}'? ", name))
    } else {
        prompt(format!("Remove file '{}'? ", name))
    }
}

fn prompt(msg: &str) -> bool {
    print(msg);
    read_prompt()
}

fn read_prompt() -> bool {
    stdio::flush();
    match buffered::BufferedReader::new(stdin()).read_line() {
        Some(line) => {
            match line.char_at(0) {
                'y' | 'Y' => true,
                'n' | 'N' => false,
                _ => {
                    print("Please enter either Y or N: ");
                    read_prompt()
                }
            }
        }
        None => true
    }
}

<commit_msg>Update rm command to fix the build<commit_after>#[crate_id(name="rm", vers="1.0.0", author="Arcterus")];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern mod extra;

use std::os;
use std::io::{stdin,stderr,stdio,fs,buffered,io_error};
use extra::getopts::groups;

enum InteractiveMode {
    InteractiveNone,
    InteractiveOnce,
    InteractiveAlways
}

impl Eq for InteractiveMode {
    fn eq(&self, other: &InteractiveMode) -> bool {
        match (*self, *other) {
            (InteractiveNone, InteractiveNone) |
            (InteractiveOnce, InteractiveOnce) |
            (InteractiveAlways, InteractiveAlways) => true,
            _ => false
        }
    }

    fn ne(&self, other: &InteractiveMode) -> bool {
        !self.eq(other)
    }
}

fn main() {
    let args = os::args();
    let program = args[0].clone();

    // TODO: make getopts support -R in addition to -r
    let opts = ~[
        groups::optflag("f", "force", "ignore nonexistent files and arguments, never prompt"),
        groups::optflag("i", "", "prompt before every removal"),
        groups::optflag("I", "", "prompt once before removing more than three files, or when removing recursively.  Less intrusive than -i, while still giving some protection against most mistakes"),
        groups::optflagopt("", "interactive", "prompt according to WHEN: never, once (-I), or always (-i).  Without WHEN, prompts always", "WHEN"),
        groups::optflag("", "one-file-system", "when removing a hierarchy recursively, skip any directory that is on a file system different from that of the corresponding command line argument (NOT IMPLEMENTED)"),
        groups::optflag("", "no-preserve-root", "do not treat '/' specially"),
        groups::optflag("", "preserve-root", "do not remove '/' (default)"),
        groups::optflag("r", "recursive", "remove directories and their contents recursively"),
        groups::optflag("d", "dir", "remove empty directories"),
        groups::optflag("v", "verbose", "explain what is being done"),
        groups::optflag("h", "help", "display this help and exit"),
        groups::optflag("V", "version", "output version information and exit")
    ];
    let matches = match groups::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            writeln!(&mut stderr() as &mut Writer,
                     "{}", f.to_err_msg());
            os::set_exit_status(1);
            return
        }
    };
    if matches.opt_present("help") {
        println("rm 1.0.0");
        println("");
        println("Usage:");
        println!("  {0:s} [OPTION]... [FILE]...", program);
        println("");
        print(groups::usage("Remove (unlink) the FILE(s).", opts));
        println("");
        println("By default, rm does not remove directories.  Use the --recursive (-r)");
        println("option to remove each listed directory, too, along with all of its contents");
        println("");
        println("To remove a file whose name starts with a '-', for example '-foo',");
        println("use one of these commands:");
        println("rm -- -foo");
        println("");
        println("rm ./-foo");
        println("");
        println("Note that if you use rm to remove a file, it might be possible to recover");
        println("some of its contents, given sufficient expertise and/or time.  For greater");
        println("assurance that the contents are truly unrecoverable, consider using shred.");
    } else if matches.opt_present("version") {
        println("rm 1.0.0");
    } else if matches.free.is_empty() {
        writeln!(&mut stderr() as &mut Writer, "Missing an argument");
        writeln!(&mut stderr() as &mut Writer,
                 "For help, try '{0:s} --help'", program);
        os::set_exit_status(1);
    } else {
        let force = matches.opt_present("force");
        let interactive =
            if matches.opt_present("i") {
                InteractiveAlways
            } else if matches.opt_present("I") {
                InteractiveOnce
            } else if matches.opt_present("interactive") {
                match matches.opt_str("interactive").unwrap() {
                    ~"none" => InteractiveNone,
                    ~"once" => InteractiveOnce,
                    ~"always" => InteractiveAlways,
                    val => {
                        writeln!(&mut stderr() as &mut Writer,
                                 "Invalid argument to interactive ({})", val);
                        os::set_exit_status(1);
                        return
                    }
                }
            } else {
                InteractiveNone
            };
        let one_fs = matches.opt_present("one-file-system");
        let preserve_root = !matches.opt_present("no-preserve-root");
        let recursive = matches.opt_present("recursive");
        let dir = matches.opt_present("dir");
        let verbose = matches.opt_present("verbose");
        if interactive == InteractiveOnce && (recursive || matches.free.len() > 3) {
            let msg =
                if recursive {
                    "Remove all arguments recursively? "
                } else {
                    "Remove all arguments? "
                };
            if !prompt(msg) {
                return;
            }
        }
        remove(matches.free, force, interactive, one_fs, preserve_root,
               recursive, dir, verbose);
    }
}

// TODO: implement one-file-system
fn remove(files: &[~str], force: bool, interactive: InteractiveMode, one_fs: bool, preserve_root: bool, recursive: bool, dir: bool, verbose: bool) {
    for filename in files.iter() {
        let file = Path::new(filename.to_owned());
        if file.exists() {
            if file.is_dir() {
                if recursive && (*filename != ~"/" || !preserve_root) {
                    remove(fs::walk_dir(&file).map(|x| x.as_str().unwrap().to_owned()).to_owned_vec(), force, interactive, one_fs, preserve_root, recursive, dir, verbose);
                    remove_dir(&file, *filename, interactive, verbose);
                } else if dir && (*filename != ~"/" || !preserve_root) {
                    remove_dir(&file, *filename, interactive, verbose);
                } else {
                    if recursive {
                        writeln!(&mut stderr() as &mut Writer,
                                 "Could not remove directory '{}'",
                                 *filename);
                    } else {
                        writeln!(&mut stderr() as &mut Writer,
                                 "Could not remove directory '{}' (did you mean to pass '-r'?)",
                                 *filename);
                    }
                    os::set_exit_status(1);
                }
            } else {
                remove_file(&file, *filename, interactive, verbose);
            }
        } else if !force {
            writeln!(&mut stderr() as &mut Writer,
                     "No such file or directory '{}'", *filename);
            os::set_exit_status(1);
        }
    }
}

fn remove_dir(path: &Path, name: &str, interactive: InteractiveMode, verbose: bool) {
    let response =
        if interactive == InteractiveAlways {
            prompt_file(path, name)
        } else {
            true
        };
    if response {
        io_error::cond.trap(|_| {
            writeln!(&mut stderr() as &mut Writer,
                     "Could not remove directory '{}'", name);
            os::set_exit_status(1);
        }).inside(|| {
            fs::rmdir(path);
            if verbose {
                println!("Removed '{}'", name);
            }
        });
    }
}

fn remove_file(path: &Path, name: &str, interactive: InteractiveMode, verbose: bool) {
    let response =
        if interactive == InteractiveAlways {
            prompt_file(path, name)
        } else {
            true
        };
    if response {
        io_error::cond.trap(|_| {
            writeln!(&mut stderr() as &mut Writer,
                     "Could not remove file '{}'", name);
            os::set_exit_status(1);
        }).inside(|| {
            fs::unlink(path);
            if verbose {
                println!("Removed '{}'", name);
            }
        });
    }
}

fn prompt_file(path: &Path, name: &str) -> bool {
    if path.is_dir() {
        prompt(format!("Remove directory '{}'? ", name))
    } else {
        prompt(format!("Remove file '{}'? ", name))
    }
}

fn prompt(msg: &str) -> bool {
    print(msg);
    read_prompt()
}

fn read_prompt() -> bool {
    stdio::flush();
    match buffered::BufferedReader::new(stdin()).read_line() {
        Some(line) => {
            match line.char_at(0) {
                'y' | 'Y' => true,
                'n' | 'N' => false,
                _ => {
                    print("Please enter either Y or N: ");
                    read_prompt()
                }
            }
        }
        None => true
    }
}

<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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 color::Color;
use geom::size::Size2D;
use geom::matrix::Matrix4;
use layers::Layer;
use std::rc::Rc;

pub struct Scene<T> {
    pub root: Option<Rc<Layer<T>>>,
    pub size: Size2D<f32>,
    pub transform: Matrix4<f32>,
    pub background_color: Color
}

pub fn Scene<T>(size: Size2D<f32>, transform: Matrix4<f32>) -> Scene<T> {
    Scene {
        root: None,
        size: size,
        transform: transform,
        background_color: Color {
                  r: 0.38f32,
                  g: 0.36f32,
                  b: 0.36f32,
                  a: 1.0f32
              }
    }
}

<commit_msg>Rename the Scene constructor to Scene::new<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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 color::Color;
use geom::size::Size2D;
use geom::matrix::Matrix4;
use layers::Layer;
use std::rc::Rc;

pub struct Scene<T> {
    pub root: Option<Rc<Layer<T>>>,
    pub size: Size2D<f32>,
    pub transform: Matrix4<f32>,
    pub background_color: Color
}

impl<T> Scene<T> {
    pub fn new(size: Size2D<f32>, transform: Matrix4<f32>) -> Scene<T> {
        Scene {
            root: None,
            size: size,
            transform: transform,
            background_color: Color {
                r: 0.38f32,
                g: 0.36f32,
                b: 0.36f32,
                a: 1.0f32
            }
        }
    }
}

<|endoftext|>


<commit_before>use std::io::Read;
use std::io::Write;

use crate::coded_output_stream::WithCodedOutputStream;
use crate::error::ProtobufError;
use crate::wire_format::check_message_size;
use crate::CodedInputStream;
use crate::CodedOutputStream;
use crate::UnknownFields;

/// Trait which is implemented by all generated message.
///
/// Note, by default all generated messages also implement [`MessageFull`](crate::MessageFull)
/// trait which provides access to reflection and features which depend on reflection
/// (text format and JSON serialization).
pub trait Message: Clone + Send + Sync + Sized + 'static {
    /// Message name as specified in `.proto` file.
    ///
    /// Message name can be accessed using
    /// [`MessageFull::descriptor_static`](crate::MessageFull::descriptor_static),
    /// but when lite runtime is requested, this field can be used.
    const NAME: &'static str;

    /// True iff all required fields are initialized.
    /// Always returns `true` for protobuf 3.
    fn is_initialized(&self) -> bool;

    /// Update this message object with fields read from given stream.
    fn merge_from(&mut self, is: &mut CodedInputStream) -> crate::Result<()>;

    /// Parse message from stream.
    fn parse_from(is: &mut CodedInputStream) -> crate::Result<Self> {
        let mut r: Self = Message::new();
        r.merge_from(is)?;
        r.check_initialized()?;
        Ok(r)
    }

    /// Write message to the stream.
    ///
    /// Sizes of this messages and nested messages must be cached
    /// by calling `compute_size` prior to this call.
    fn write_to_with_cached_sizes(&self, os: &mut CodedOutputStream) -> crate::Result<()>;

    /// Compute and cache size of this message and all nested messages.
    ///
    /// Note if the computation overflows u32, the cached size is stored truncated.
    fn compute_size(&self) -> u64;

    /// Get size previously computed by `compute_size`.
    ///
    /// Note if message size exceeds u32, the cached size is stored truncated.
    fn cached_size(&self) -> u32;

    /// Write the message to the stream.
    ///
    /// Results in error if message is not fully initialized.
    fn write_to(&self, os: &mut CodedOutputStream) -> crate::Result<()> {
        self.check_initialized()?;

        // cache sizes
        self.compute_size();
        // TODO: reserve additional
        self.write_to_with_cached_sizes(os)?;

        Ok(())
    }

    /// Write the message to the stream prepending the message with message length
    /// encoded as varint.
    fn write_length_delimited_to(&self, os: &mut CodedOutputStream) -> crate::Result<()> {
        let size = self.compute_size();
        let size = check_message_size(size)?;
        os.write_raw_varint32(size as u32)?;

        let written = os.total_bytes_written();

        self.write_to_with_cached_sizes(os)?;

        // Self-check.
        assert_eq!(
            written + size as u64,
            os.total_bytes_written(),
            "Expected to write {}, actually wrote {}",
            size,
            os.total_bytes_written() - written
        );

        Ok(())
    }

    /// Write the message to the vec, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_vec(&self, vec: &mut Vec<u8>) -> crate::Result<()> {
        let mut os = CodedOutputStream::vec(vec);
        self.write_length_delimited_to(&mut os)?;
        os.flush()?;
        Ok(())
    }

    /// Update this message object with fields read from given stream.
    fn merge_from_bytes(&mut self, bytes: &[u8]) -> crate::Result<()> {
        let mut is = CodedInputStream::from_bytes(bytes);
        self.merge_from(&mut is)
    }

    /// Parse message from reader.
    /// Parse stops on EOF or when error encountered.
    fn parse_from_reader(reader: &mut dyn Read) -> crate::Result<Self>
    where
        Self: Sized,
    {
        let mut is = CodedInputStream::new(reader);
        let r = Message::parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }

    /// Parse message from byte array.
    fn parse_from_bytes(bytes: &[u8]) -> crate::Result<Self>
    where
        Self: Sized,
    {
        let mut is = CodedInputStream::from_bytes(bytes);
        let r = Message::parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }

    /// Parse message from `Bytes` object.
    /// Resulting message may share references to the passed bytes object.
    #[cfg(feature = "bytes")]
    fn parse_from_tokio_bytes(bytes: &bytes::Bytes) -> crate::Result<Self>
    where
        Self: Sized,
    {
        let mut is = CodedInputStream::from_tokio_bytes(bytes);
        let r = Self::parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }

    /// Check if all required fields of this object are initialized.
    fn check_initialized(&self) -> crate::Result<()> {
        if !self.is_initialized() {
            Err(ProtobufError::MessageNotInitialized(Self::NAME.to_owned()).into())
        } else {
            Ok(())
        }
    }

    /// Write the message to the writer.
    fn write_to_writer(&self, w: &mut dyn Write) -> crate::Result<()> {
        w.with_coded_output_stream(|os| self.write_to(os))
    }

    /// Write the message to bytes vec.
    fn write_to_vec(&self, v: &mut Vec<u8>) -> crate::Result<()> {
        v.with_coded_output_stream(|os| self.write_to(os))
    }

    /// Write the message to bytes vec.
    ///
    /// > **Note**: You can use [`Message::parse_from_bytes`]
    /// to do the reverse.
    fn write_to_bytes(&self) -> crate::Result<Vec<u8>> {
        self.check_initialized()?;

        let size = self.compute_size() as usize;
        let mut v = Vec::with_capacity(size);
        {
            let mut os = CodedOutputStream::vec(&mut v);
            self.write_to_with_cached_sizes(&mut os)?;
            os.flush()?;
        }
        Ok(v)
    }

    /// Write the message to the writer, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_writer(&self, w: &mut dyn Write) -> crate::Result<()> {
        w.with_coded_output_stream(|os| self.write_length_delimited_to(os))
    }

    /// Write the message to the bytes vec, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_bytes(&self) -> crate::Result<Vec<u8>> {
        let mut v = Vec::new();
        v.with_coded_output_stream(|os| self.write_length_delimited_to(os))?;
        Ok(v)
    }

    /// Get a reference to unknown fields.
    fn unknown_fields(&self) -> &UnknownFields;
    /// Get a mutable reference to unknown fields.
    fn mut_unknown_fields(&mut self) -> &mut UnknownFields;

    /// Create an empty message object.
    ///
    /// ```
    /// # use protobuf::MessageFull;
    /// # fn foo<MyMessage: MessageFull>() {
    /// let m = MyMessage::new();
    /// # }
    /// ```
    fn new() -> Self;

    /// Reset all fields.
    fn clear(&mut self) {
        *self = Self::new();
    }

    /// Return a pointer to default immutable message with static lifetime.
    ///
    /// ```
    /// # use protobuf::MessageFull;
    /// # fn foo<MyMessage: MessageFull>() {
    /// let m: &MyMessage = MyMessage::default_instance();
    /// # }
    /// ```
    fn default_instance() -> &'static Self;
}
<commit_msg>Code cleanup<commit_after>use std::io::Read;
use std::io::Write;

use crate::coded_output_stream::WithCodedOutputStream;
use crate::error::ProtobufError;
use crate::wire_format::check_message_size;
use crate::CodedInputStream;
use crate::CodedOutputStream;
use crate::UnknownFields;

/// Trait which is implemented by all generated message.
///
/// Note, by default all generated messages also implement [`MessageFull`](crate::MessageFull)
/// trait which provides access to reflection and features which depend on reflection
/// (text format and JSON serialization).
pub trait Message: Clone + Send + Sync + Sized + 'static {
    /// Message name as specified in `.proto` file.
    ///
    /// Message name can be accessed using
    /// [`MessageFull::descriptor_static`](crate::MessageFull::descriptor_static),
    /// but when lite runtime is requested, this field can be used.
    const NAME: &'static str;

    /// True iff all required fields are initialized.
    /// Always returns `true` for protobuf 3.
    fn is_initialized(&self) -> bool;

    /// Update this message object with fields read from given stream.
    fn merge_from(&mut self, is: &mut CodedInputStream) -> crate::Result<()>;

    /// Parse message from stream.
    fn parse_from(is: &mut CodedInputStream) -> crate::Result<Self> {
        let mut r: Self = Message::new();
        r.merge_from(is)?;
        r.check_initialized()?;
        Ok(r)
    }

    /// Write message to the stream.
    ///
    /// Sizes of this messages and nested messages must be cached
    /// by calling `compute_size` prior to this call.
    fn write_to_with_cached_sizes(&self, os: &mut CodedOutputStream) -> crate::Result<()>;

    /// Compute and cache size of this message and all nested messages.
    ///
    /// Note if the computation overflows u32, the cached size is stored truncated.
    fn compute_size(&self) -> u64;

    /// Get size previously computed by `compute_size`.
    ///
    /// Note if message size exceeds u32, the cached size is stored truncated.
    fn cached_size(&self) -> u32;

    /// Write the message to the stream.
    ///
    /// Results in error if message is not fully initialized.
    fn write_to(&self, os: &mut CodedOutputStream) -> crate::Result<()> {
        self.check_initialized()?;

        // cache sizes
        self.compute_size();
        // TODO: reserve additional
        self.write_to_with_cached_sizes(os)?;

        Ok(())
    }

    /// Write the message to the stream prepending the message with message length
    /// encoded as varint.
    fn write_length_delimited_to(&self, os: &mut CodedOutputStream) -> crate::Result<()> {
        let size = self.compute_size();
        let size = check_message_size(size)?;
        os.write_raw_varint32(size as u32)?;

        let written = os.total_bytes_written();

        self.write_to_with_cached_sizes(os)?;

        // Self-check.
        assert_eq!(
            written + size as u64,
            os.total_bytes_written(),
            "Expected to write {}, actually wrote {}",
            size,
            os.total_bytes_written() - written
        );

        Ok(())
    }

    /// Write the message to the vec, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_vec(&self, vec: &mut Vec<u8>) -> crate::Result<()> {
        let mut os = CodedOutputStream::vec(vec);
        self.write_length_delimited_to(&mut os)?;
        os.flush()?;
        Ok(())
    }

    /// Update this message object with fields read from given stream.
    fn merge_from_bytes(&mut self, bytes: &[u8]) -> crate::Result<()> {
        let mut is = CodedInputStream::from_bytes(bytes);
        self.merge_from(&mut is)
    }

    /// Parse message from reader.
    /// Parse stops on EOF or when error encountered.
    fn parse_from_reader(reader: &mut dyn Read) -> crate::Result<Self> {
        let mut is = CodedInputStream::new(reader);
        let r = Message::parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }

    /// Parse message from byte array.
    fn parse_from_bytes(bytes: &[u8]) -> crate::Result<Self> {
        let mut is = CodedInputStream::from_bytes(bytes);
        let r = Message::parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }

    /// Parse message from `Bytes` object.
    /// Resulting message may share references to the passed bytes object.
    #[cfg(feature = "bytes")]
    fn parse_from_tokio_bytes(bytes: &bytes::Bytes) -> crate::Result<Self> {
        let mut is = CodedInputStream::from_tokio_bytes(bytes);
        let r = Self::parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }

    /// Check if all required fields of this object are initialized.
    fn check_initialized(&self) -> crate::Result<()> {
        if !self.is_initialized() {
            Err(ProtobufError::MessageNotInitialized(Self::NAME.to_owned()).into())
        } else {
            Ok(())
        }
    }

    /// Write the message to the writer.
    fn write_to_writer(&self, w: &mut dyn Write) -> crate::Result<()> {
        w.with_coded_output_stream(|os| self.write_to(os))
    }

    /// Write the message to bytes vec.
    fn write_to_vec(&self, v: &mut Vec<u8>) -> crate::Result<()> {
        v.with_coded_output_stream(|os| self.write_to(os))
    }

    /// Write the message to bytes vec.
    ///
    /// > **Note**: You can use [`Message::parse_from_bytes`]
    /// to do the reverse.
    fn write_to_bytes(&self) -> crate::Result<Vec<u8>> {
        self.check_initialized()?;

        let size = self.compute_size() as usize;
        let mut v = Vec::with_capacity(size);
        {
            let mut os = CodedOutputStream::vec(&mut v);
            self.write_to_with_cached_sizes(&mut os)?;
            os.flush()?;
        }
        Ok(v)
    }

    /// Write the message to the writer, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_writer(&self, w: &mut dyn Write) -> crate::Result<()> {
        w.with_coded_output_stream(|os| self.write_length_delimited_to(os))
    }

    /// Write the message to the bytes vec, prepend the message with message length
    /// encoded as varint.
    fn write_length_delimited_to_bytes(&self) -> crate::Result<Vec<u8>> {
        let mut v = Vec::new();
        v.with_coded_output_stream(|os| self.write_length_delimited_to(os))?;
        Ok(v)
    }

    /// Get a reference to unknown fields.
    fn unknown_fields(&self) -> &UnknownFields;
    /// Get a mutable reference to unknown fields.
    fn mut_unknown_fields(&mut self) -> &mut UnknownFields;

    /// Create an empty message object.
    ///
    /// ```
    /// # use protobuf::MessageFull;
    /// # fn foo<MyMessage: MessageFull>() {
    /// let m = MyMessage::new();
    /// # }
    /// ```
    fn new() -> Self;

    /// Reset all fields.
    fn clear(&mut self) {
        *self = Self::new();
    }

    /// Return a pointer to default immutable message with static lifetime.
    ///
    /// ```
    /// # use protobuf::MessageFull;
    /// # fn foo<MyMessage: MessageFull>() {
    /// let m: &MyMessage = MyMessage::default_instance();
    /// # }
    /// ```
    fn default_instance() -> &'static Self;
}
<|endoftext|>