<commit_before>use syntax::ast::punc::*;
use syntax::ast::token::*;
use std::io::{BufReader, BufferedReader, Buffer, IoError, IoResult, EndOfFile};
use std::char::from_u32;
use std::num::from_str_radix;
use std::from_str::FromStr;
/// A Javascript lexer
pub struct Lexer<B> {
    /// The list of tokens generated so far
    pub tokens : Vec<Token>,
    /// The current line number in the script
    line_number : uint,
    /// The current column number in the script
    column_number : uint,
    /// The reader
    buffer: B,
    /// The peeked character buffer
    peek_buffer: String
}
impl<B:Buffer> Lexer<B> {
    /// Creates a new lexer with empty buffers
    pub fn new(buffer: B) -> Lexer<B> {
        Lexer {
            tokens: Vec::new(),
            line_number: 1,
            column_number: 0,
            buffer: buffer,
            peek_buffer: String::new()
        }
    }
    #[inline(always)]
    fn push_token(&mut self, tk:TokenData) {
        self.tokens.push(Token::new(tk, self.line_number, self.column_number))
    }
    #[inline(always)]
    fn push_punc(&mut self, punc:Punctuator) {
        self.push_token(TPunctuator(punc));
    }
    /// Processes an input stream from a string into an array of tokens
    pub fn lex_str(script:&str) -> Vec<Token> {
        let script_bytes:&[u8] = script.as_bytes();
        let reader = BufReader::new(script_bytes);
        let buf_reader = BufferedReader::new(reader);
        let mut lexer = Lexer::new(buf_reader);
        lexer.lex().unwrap();
        lexer.tokens
    }
    fn next(&mut self) -> IoResult<char> {
        if self.peek_buffer.len() == 0 {
            self.buffer.read_char()
        } else {
            Ok(match self.peek_buffer.pop_char() {
                Some(v) => v,
                None => unreachable!()
            })
        }
    }
    fn next_is(&mut self, peek:char) -> bool {
        if self.peek_buffer.len() > 0 {
            let matched = self.peek_buffer.as_slice().char_at(self.peek_buffer.len() - 1) == peek;
            if matched {
                self.peek_buffer.pop_char();
            }
            matched
        } else {
            match self.buffer.read_char() {
                Ok(ch) if ch == peek => {
                    self.column_number += 1;
                    true
                },
                Ok(ch) if ch != peek => {
                    self.peek_buffer.push_char(ch);
                    false
                },
                _ => false
            }
        }
    }
    /// Processes an input stream from the `buffer` into a vector of tokens
    pub fn lex(&mut self) -> IoResult<()> {
        loop {
            let ch = match self.next() {
                Ok(ch) => ch,
                Err(IoError {kind: EndOfFile, ..}) => break,
                Err(err) => return Err(err)
            };
            self.column_number += 1;
            match ch {
                '"' | '\'' => {
                    let mut buf = String::new();
                    loop {
                        match try!(self.next()) {
                            '\'' if ch == '\'' => {
                                break;
                            },
                            '"' if ch == '"' => {
                                break;
                            },
                            '\\' => {
                                let escape = try!(self.next());
                                if escape != '\n' {
                                    let escaped_ch = match escape {
                                        'n' => '\n',
                                        'r' => '\r',
                                        't' => '\t',
                                        'b' => '\x08',
                                        'f' => '\x0c',
                                        '0' => '\0',
                                        'x' => {
                                            let mut nums = String::with_capacity(2);
                                            for _ in range(0, 2) {
                                                nums.push_char(try!(self.next()));
                                            }
                                            self.column_number += 2;
                                            let as_num = match from_str_radix(nums.as_slice(), 16) {
                                                Some(v) => v,
                                                None => 0
                                            };
                                            match from_u32(as_num) {
                                                Some(v) => v,
                                                None => fail!("{}:{}: {} is not a valid unicode scalar value", self.line_number, self.column_number, as_num)
                                            }
                                        },
                                        'u' => {
                                            let mut nums = String::new();
                                            for _ in range(0, 4) {
                                                nums.push_char(try!(self.next()));
                                            }
                                            self.column_number += 4;
                                            let as_num = match from_str_radix(nums.as_slice(), 16) {
                                                Some(v) => v,
                                                None => 0
                                            };
                                            match from_u32(as_num) {
                                                Some(v) => v,
                                                None => fail!("{}:{}: {} is not a valid unicode scalar value", self.line_number, self.column_number, as_num)
                                            }
                                        },
                                        '\'' | '"' => escape,
                                        _ => fail!("{}:{}: Invalid escape `{}`", self.line_number, self.column_number, ch)
                                    };
                                    buf.push_char(escaped_ch);
                                }
                            },
                            ch => buf.push_char(ch)
                        }
                    }
                    self.push_token(TStringLiteral(buf))
                },
                '0' if self.next_is('x') => {
                    let mut buf = String::new();
                    loop {
                        match try!(self.next()) {
                            ch if ch.is_digit_radix(16) => buf.push_char(ch),
                            ch => {
                                self.peek_buffer.push_char(ch);
                                break;
                            }
                        }
                    }
                    self.push_token(TNumericLiteral(from_str_radix(buf.as_slice(), 16).unwrap()));
                },
                '0' => {
                    let mut buf = "0".into_string();
                    let mut gone_decimal = false;
                    loop {
                        let ch = self.next();
                        match ch {
                            Ok(ch) if ch.is_digit_radix(8) =>
                                buf.push_char(ch),
                            Ok('8') | Ok('9') | Ok('.') => {
                                gone_decimal = true;
                                buf.push_char(ch.unwrap());
                            },
                            Ok(ch) => {
                                self.peek_buffer.push_char(ch);
                                break;
                            },
                            Err(IoError {kind: EndOfFile, ..}) =>
                                break,
                            Err(err) =>
                                return Err(err)
                        }
                    }
                    self.push_token(TNumericLiteral(if gone_decimal {
                        from_str(buf.as_slice())
                    } else {
                        from_str_radix(buf.as_slice(), 8)
                    }.unwrap()));
                },
                _ if ch.is_digit() => {
                    let mut buf = String::new();
                    buf.push_char(ch);
                    loop {
                        let ch = try!(self.next());
                        match ch {
                            '.' => buf.push_char(ch),
                            _ if ch.is_digit() => buf.push_char(ch),
                            _ => {
                                self.peek_buffer.push_char(ch);
                                break;
                            }
                        }
                    }
                    self.push_token(TNumericLiteral(from_str(buf.as_slice()).unwrap()));
                },
                _ if ch.is_alphabetic() || ch == '$' || ch == '_' => {
                    let mut buf = String::new();
                    buf.push_char(ch);
                    loop {
                        let ch = try!(self.next());
                        match ch {
                            _ if ch.is_alphabetic() || ch.is_digit() || ch == '_' => buf.push_char(ch),
                            _ => {
                                self.peek_buffer.push_char(ch);
                                break;
                            }
                        }
                    }
                    self.push_token(match buf.as_slice() {
                        "true" => TBooleanLiteral(true),
                        "false" => TBooleanLiteral(false),
                        "null" => TNullLiteral,
                        slice => match FromStr::from_str(slice) {
                            Some(keyword) => TKeyword(keyword),
                            None => TIdentifier(buf.clone())
                        }
                    });
                },
                ';' => self.push_punc(PSemicolon),
                ':' => self.push_punc(PColon),
                '.' => self.push_punc(PDot),
                '(' => self.push_punc(POpenParen),
                ')' => self.push_punc(PCloseParen),
                ',' => self.push_punc(PComma),
                '{' => self.push_punc(POpenBlock),
                '}' => self.push_punc(PCloseBlock),
                '[' => self.push_punc(POpenBracket),
                ']' => self.push_punc(PCloseBracket),
                '?' => self.push_punc(PQuestion),
                '/' if self.next_is('/') => {
                    let mut buf = String::new();
                    loop {
                        match try!(self.next()) {
                            '\n' => break,
                            ch => buf.push_char(ch)
                        }
                    }
                    self.push_token(TComment(buf));
                },
                '/' if self.next_is('*') => {
                    let mut buf = String::new();
                    loop {
                        match try!(self.next()) {
                            '\n' => break,
                            '*' if self.next_is('/') => break,
                            ch => buf.push_char(ch)
                        }
                    }
                    self.push_token(TComment(buf));
                },
                '/' if self.next_is('=') =>
                    self.push_punc(PAssignDiv),
                '/' => self.push_punc(PDiv),
                '*' if self.next_is('=') =>
                    self.push_punc(PAssignMul),
                '*' => self.push_punc(PMul),
                '+' if self.next_is('=') =>
                    self.push_punc(PAssignAdd),
                '+' if self.next_is('+') =>
                    self.push_punc(PInc),
                '+' => self.push_punc(PAdd),
                '-' if self.next_is('=') =>
                    self.push_punc(PAssignSub),
                '-' if self.next_is('-') =>
                    self.push_punc(PDec),
                '-' => self.push_punc(PSub),
                '%' if self.next_is('=') =>
                    self.push_punc(PAssignMod),
                '%' => self.push_punc(PMod),
                '|' if self.next_is('|') =>
                    self.push_punc(PBoolOr),
                '|' if self.next_is('=') =>
                    self.push_punc(PAssignOr),
                '|' => self.push_punc(POr),
                '&' if self.next_is('&') =>
                    self.push_punc(PBoolAnd),
                '&' if self.next_is('=') =>
                    self.push_punc(PAssignAnd),
                '&' => self.push_punc(PAnd),
                '^' if self.next_is('=') =>
                    self.push_punc(PAssignXor),
                '^' => self.push_punc(PXor),
                '=' if self.next_is('>') =>
                    self.push_punc(PArrow),
                '=' if self.next_is('=') => {
                    let punc = if self.next_is('=') {
                        PStrictEq
                    } else {
                        PEq
                    };
                    self.push_punc(punc)
                },
                '=' => self.push_punc(PAssign),
                '<' if self.next_is('=') =>
                    self.push_punc(PLessThanOrEq),
                '<' if self.next_is('<') => {
                    let punc = if self.next_is('=') {
                        PAssignLeftSh
                    } else {
                        PLeftSh
                    };
                    self.push_punc(punc)
                },
                '<' => self.push_punc(PLessThan),
                '>' if self.next_is('=') =>
                    self.push_punc(PGreaterThanOrEq),
                '>' if self.next_is('>') => {
                    let punc = if self.next_is('=') {
                        PAssignRightSh
                    } else if self.next_is('>') {
                        if self.next_is('=') {
                            PAssignURightSh
                        } else {
                            PURightSh
                        }
                    } else {
                        PRightSh
                    };
                    self.push_punc(punc)
                },
                '>' => self.push_punc(PGreaterThan),
                '!' if self.next_is('=') => {
                    let punc = if self.next_is('=') {
                        PStrictNotEq
                    } else {
                        PNotEq
                    };
                    self.push_punc(punc)
                },
                '!' => self.push_punc(PNot),
                '~' => self.push_punc(PNeg),
                '\n' | '\u2028'|'\u2029' => {
                    self.line_number += 1;
                    self.column_number = 0;
                },
                '\r' => {
                    self.column_number = 0;
                },
                ' ' => (),
                ch => fail!("{}:{}: Unexpected '{}'", self.line_number, self.column_number, ch)
            };
        };
        Ok(())
    }
}<commit_msg>Explicit number types in `range` in Lexer<commit_after>use syntax::ast::punc::*;
use syntax::ast::token::*;
use std::io::{BufReader, BufferedReader, Buffer, IoError, IoResult, EndOfFile};
use std::char::from_u32;
use std::num::from_str_radix;
use std::from_str::FromStr;
/// A Javascript lexer
pub struct Lexer<B> {
    /// The list of tokens generated so far
    pub tokens : Vec<Token>,
    /// The current line number in the script
    line_number : uint,
    /// The current column number in the script
    column_number : uint,
    /// The reader
    buffer: B,
    /// The peeked character buffer
    peek_buffer: String
}
impl<B:Buffer> Lexer<B> {
    /// Creates a new lexer with empty buffers
    pub fn new(buffer: B) -> Lexer<B> {
        Lexer {
            tokens: Vec::new(),
            line_number: 1,
            column_number: 0,
            buffer: buffer,
            peek_buffer: String::new()
        }
    }
    #[inline(always)]
    fn push_token(&mut self, tk:TokenData) {
        self.tokens.push(Token::new(tk, self.line_number, self.column_number))
    }
    #[inline(always)]
    fn push_punc(&mut self, punc:Punctuator) {
        self.push_token(TPunctuator(punc));
    }
    /// Processes an input stream from a string into an array of tokens
    pub fn lex_str(script:&str) -> Vec<Token> {
        let script_bytes:&[u8] = script.as_bytes();
        let reader = BufReader::new(script_bytes);
        let buf_reader = BufferedReader::new(reader);
        let mut lexer = Lexer::new(buf_reader);
        lexer.lex().unwrap();
        lexer.tokens
    }
    fn next(&mut self) -> IoResult<char> {
        if self.peek_buffer.len() == 0 {
            self.buffer.read_char()
        } else {
            Ok(match self.peek_buffer.pop_char() {
                Some(v) => v,
                None => unreachable!()
            })
        }
    }
    fn next_is(&mut self, peek:char) -> bool {
        if self.peek_buffer.len() > 0 {
            let matched = self.peek_buffer.as_slice().char_at(self.peek_buffer.len() - 1) == peek;
            if matched {
                self.peek_buffer.pop_char();
            }
            matched
        } else {
            match self.buffer.read_char() {
                Ok(ch) if ch == peek => {
                    self.column_number += 1;
                    true
                },
                Ok(ch) if ch != peek => {
                    self.peek_buffer.push_char(ch);
                    false
                },
                _ => false
            }
        }
    }
    /// Processes an input stream from the `buffer` into a vector of tokens
    pub fn lex(&mut self) -> IoResult<()> {
        loop {
            let ch = match self.next() {
                Ok(ch) => ch,
                Err(IoError {kind: EndOfFile, ..}) => break,
                Err(err) => return Err(err)
            };
            self.column_number += 1;
            match ch {
                '"' | '\'' => {
                    let mut buf = String::new();
                    loop {
                        match try!(self.next()) {
                            '\'' if ch == '\'' => {
                                break;
                            },
                            '"' if ch == '"' => {
                                break;
                            },
                            '\\' => {
                                let escape = try!(self.next());
                                if escape != '\n' {
                                    let escaped_ch = match escape {
                                        'n' => '\n',
                                        'r' => '\r',
                                        't' => '\t',
                                        'b' => '\x08',
                                        'f' => '\x0c',
                                        '0' => '\0',
                                        'x' => {
                                            let mut nums = String::with_capacity(2);
                                            for _ in range(0u, 2u) {
                                                nums.push_char(try!(self.next()));
                                            }
                                            self.column_number += 2;
                                            let as_num = match from_str_radix(nums.as_slice(), 16) {
                                                Some(v) => v,
                                                None => 0
                                            };
                                            match from_u32(as_num) {
                                                Some(v) => v,
                                                None => fail!("{}:{}: {} is not a valid unicode scalar value", self.line_number, self.column_number, as_num)
                                            }
                                        },
                                        'u' => {
                                            let mut nums = String::new();
                                            for _ in range(0, 4) {
                                                nums.push_char(try!(self.next()));
                                            }
                                            self.column_number += 4;
                                            let as_num = match from_str_radix(nums.as_slice(), 16) {
                                                Some(v) => v,
                                                None => 0
                                            };
                                            match from_u32(as_num) {
                                                Some(v) => v,
                                                None => fail!("{}:{}: {} is not a valid unicode scalar value", self.line_number, self.column_number, as_num)
                                            }
                                        },
                                        '\'' | '"' => escape,
                                        _ => fail!("{}:{}: Invalid escape `{}`", self.line_number, self.column_number, ch)
                                    };
                                    buf.push_char(escaped_ch);
                                }
                            },
                            ch => buf.push_char(ch)
                        }
                    }
                    self.push_token(TStringLiteral(buf))
                },
                '0' if self.next_is('x') => {
                    let mut buf = String::new();
                    loop {
                        match try!(self.next()) {
                            ch if ch.is_digit_radix(16) => buf.push_char(ch),
                            ch => {
                                self.peek_buffer.push_char(ch);
                                break;
                            }
                        }
                    }
                    self.push_token(TNumericLiteral(from_str_radix(buf.as_slice(), 16).unwrap()));
                },
                '0' => {
                    let mut buf = "0".into_string();
                    let mut gone_decimal = false;
                    loop {
                        let ch = self.next();
                        match ch {
                            Ok(ch) if ch.is_digit_radix(8) =>
                                buf.push_char(ch),
                            Ok('8') | Ok('9') | Ok('.') => {
                                gone_decimal = true;
                                buf.push_char(ch.unwrap());
                            },
                            Ok(ch) => {
                                self.peek_buffer.push_char(ch);
                                break;
                            },
                            Err(IoError {kind: EndOfFile, ..}) =>
                                break,
                            Err(err) =>
                                return Err(err)
                        }
                    }
                    self.push_token(TNumericLiteral(if gone_decimal {
                        from_str(buf.as_slice())
                    } else {
                        from_str_radix(buf.as_slice(), 8)
                    }.unwrap()));
                },
                _ if ch.is_digit() => {
                    let mut buf = String::new();
                    buf.push_char(ch);
                    loop {
                        let ch = try!(self.next());
                        match ch {
                            '.' => buf.push_char(ch),
                            _ if ch.is_digit() => buf.push_char(ch),
                            _ => {
                                self.peek_buffer.push_char(ch);
                                break;
                            }
                        }
                    }
                    self.push_token(TNumericLiteral(from_str(buf.as_slice()).unwrap()));
                },
                _ if ch.is_alphabetic() || ch == '$' || ch == '_' => {
                    let mut buf = String::new();
                    buf.push_char(ch);
                    loop {
                        let ch = try!(self.next());
                        match ch {
                            _ if ch.is_alphabetic() || ch.is_digit() || ch == '_' => buf.push_char(ch),
                            _ => {
                                self.peek_buffer.push_char(ch);
                                break;
                            }
                        }
                    }
                    self.push_token(match buf.as_slice() {
                        "true" => TBooleanLiteral(true),
                        "false" => TBooleanLiteral(false),
                        "null" => TNullLiteral,
                        slice => match FromStr::from_str(slice) {
                            Some(keyword) => TKeyword(keyword),
                            None => TIdentifier(buf.clone())
                        }
                    });
                },
                ';' => self.push_punc(PSemicolon),
                ':' => self.push_punc(PColon),
                '.' => self.push_punc(PDot),
                '(' => self.push_punc(POpenParen),
                ')' => self.push_punc(PCloseParen),
                ',' => self.push_punc(PComma),
                '{' => self.push_punc(POpenBlock),
                '}' => self.push_punc(PCloseBlock),
                '[' => self.push_punc(POpenBracket),
                ']' => self.push_punc(PCloseBracket),
                '?' => self.push_punc(PQuestion),
                '/' if self.next_is('/') => {
                    let mut buf = String::new();
                    loop {
                        match try!(self.next()) {
                            '\n' => break,
                            ch => buf.push_char(ch)
                        }
                    }
                    self.push_token(TComment(buf));
                },
                '/' if self.next_is('*') => {
                    let mut buf = String::new();
                    loop {
                        match try!(self.next()) {
                            '\n' => break,
                            '*' if self.next_is('/') => break,
                            ch => buf.push_char(ch)
                        }
                    }
                    self.push_token(TComment(buf));
                },
                '/' if self.next_is('=') =>
                    self.push_punc(PAssignDiv),
                '/' => self.push_punc(PDiv),
                '*' if self.next_is('=') =>
                    self.push_punc(PAssignMul),
                '*' => self.push_punc(PMul),
                '+' if self.next_is('=') =>
                    self.push_punc(PAssignAdd),
                '+' if self.next_is('+') =>
                    self.push_punc(PInc),
                '+' => self.push_punc(PAdd),
                '-' if self.next_is('=') =>
                    self.push_punc(PAssignSub),
                '-' if self.next_is('-') =>
                    self.push_punc(PDec),
                '-' => self.push_punc(PSub),
                '%' if self.next_is('=') =>
                    self.push_punc(PAssignMod),
                '%' => self.push_punc(PMod),
                '|' if self.next_is('|') =>
                    self.push_punc(PBoolOr),
                '|' if self.next_is('=') =>
                    self.push_punc(PAssignOr),
                '|' => self.push_punc(POr),
                '&' if self.next_is('&') =>
                    self.push_punc(PBoolAnd),
                '&' if self.next_is('=') =>
                    self.push_punc(PAssignAnd),
                '&' => self.push_punc(PAnd),
                '^' if self.next_is('=') =>
                    self.push_punc(PAssignXor),
                '^' => self.push_punc(PXor),
                '=' if self.next_is('>') =>
                    self.push_punc(PArrow),
                '=' if self.next_is('=') => {
                    let punc = if self.next_is('=') {
                        PStrictEq
                    } else {
                        PEq
                    };
                    self.push_punc(punc)
                },
                '=' => self.push_punc(PAssign),
                '<' if self.next_is('=') =>
                    self.push_punc(PLessThanOrEq),
                '<' if self.next_is('<') => {
                    let punc = if self.next_is('=') {
                        PAssignLeftSh
                    } else {
                        PLeftSh
                    };
                    self.push_punc(punc)
                },
                '<' => self.push_punc(PLessThan),
                '>' if self.next_is('=') =>
                    self.push_punc(PGreaterThanOrEq),
                '>' if self.next_is('>') => {
                    let punc = if self.next_is('=') {
                        PAssignRightSh
                    } else if self.next_is('>') {
                        if self.next_is('=') {
                            PAssignURightSh
                        } else {
                            PURightSh
                        }
                    } else {
                        PRightSh
                    };
                    self.push_punc(punc)
                },
                '>' => self.push_punc(PGreaterThan),
                '!' if self.next_is('=') => {
                    let punc = if self.next_is('=') {
                        PStrictNotEq
                    } else {
                        PNotEq
                    };
                    self.push_punc(punc)
                },
                '!' => self.push_punc(PNot),
                '~' => self.push_punc(PNeg),
                '\n' | '\u2028'|'\u2029' => {
                    self.line_number += 1;
                    self.column_number = 0;
                },
                '\r' => {
                    self.column_number = 0;
                },
                ' ' => (),
                ch => fail!("{}:{}: Unexpected '{}'", self.line_number, self.column_number, ch)
            };
        };
        Ok(())
    }
}<|endoftext|>


<commit_before>use self::Namespace::*;

use crate::hir;
use crate::hir::def_id::{DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
use crate::ty;

use rustc_macros::HashStable;
use rustc_span::hygiene::MacroKind;
use rustc_span::Span;
use syntax::ast;
use syntax::ast::NodeId;

use std::fmt::Debug;

/// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct.
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
pub enum CtorOf {
    /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit struct.
    Struct,
    /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit variant.
    Variant,
}

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
pub enum CtorKind {
    /// Constructor function automatically created by a tuple struct/variant.
    Fn,
    /// Constructor constant automatically created by a unit struct/variant.
    Const,
    /// Unusable name in value namespace created by a struct variant.
    Fictive,
}

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
pub enum NonMacroAttrKind {
    /// Single-segment attribute defined by the language (`#[inline]`)
    Builtin,
    /// Multi-segment custom attribute living in a "tool module" (`#[rustfmt::skip]`).
    Tool,
    /// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`).
    DeriveHelper,
    /// Single-segment custom attribute registered with `#[register_attr]`.
    Registered,
}

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
pub enum DefKind {
    // Type namespace
    Mod,
    /// Refers to the struct itself, `DefKind::Ctor` refers to its constructor if it exists.
    Struct,
    Union,
    Enum,
    /// Refers to the variant itself, `DefKind::Ctor` refers to its constructor if it exists.
    Variant,
    Trait,
    /// `type Foo = impl Bar;`
    OpaqueTy,
    /// `type Foo = Bar;`
    TyAlias,
    ForeignTy,
    TraitAlias,
    AssocTy,
    /// `type Foo = impl Bar;`
    AssocOpaqueTy,
    TyParam,

    // Value namespace
    Fn,
    Const,
    ConstParam,
    Static,
    /// Refers to the struct or enum variant's constructor.
    Ctor(CtorOf, CtorKind),
    Method,
    AssocConst,

    // Macro namespace
    Macro(MacroKind),
}

impl DefKind {
    pub fn descr(self, def_id: DefId) -> &'static str {
        match self {
            DefKind::Fn => "function",
            DefKind::Mod if def_id.index == CRATE_DEF_INDEX && def_id.krate != LOCAL_CRATE => {
                "crate"
            }
            DefKind::Mod => "module",
            DefKind::Static => "static",
            DefKind::Enum => "enum",
            DefKind::Variant => "variant",
            DefKind::Ctor(CtorOf::Variant, CtorKind::Fn) => "tuple variant",
            DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => "unit variant",
            DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive) => "struct variant",
            DefKind::Struct => "struct",
            DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct",
            DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct",
            DefKind::Ctor(CtorOf::Struct, CtorKind::Fictive) => {
                bug!("impossible struct constructor")
            }
            DefKind::OpaqueTy => "opaque type",
            DefKind::TyAlias => "type alias",
            DefKind::TraitAlias => "trait alias",
            DefKind::AssocTy => "associated type",
            DefKind::AssocOpaqueTy => "associated opaque type",
            DefKind::Union => "union",
            DefKind::Trait => "trait",
            DefKind::ForeignTy => "foreign type",
            DefKind::Method => "method",
            DefKind::Const => "constant",
            DefKind::AssocConst => "associated constant",
            DefKind::TyParam => "type parameter",
            DefKind::ConstParam => "const parameter",
            DefKind::Macro(macro_kind) => macro_kind.descr(),
        }
    }

    /// Gets an English article for the definition.
    pub fn article(&self) -> &'static str {
        match *self {
            DefKind::AssocTy
            | DefKind::AssocConst
            | DefKind::AssocOpaqueTy
            | DefKind::Enum
            | DefKind::OpaqueTy => "an",
            DefKind::Macro(macro_kind) => macro_kind.article(),
            _ => "a",
        }
    }

    pub fn matches_ns(&self, ns: Namespace) -> bool {
        match self {
            DefKind::Mod
            | DefKind::Struct
            | DefKind::Union
            | DefKind::Enum
            | DefKind::Variant
            | DefKind::Trait
            | DefKind::OpaqueTy
            | DefKind::TyAlias
            | DefKind::ForeignTy
            | DefKind::TraitAlias
            | DefKind::AssocTy
            | DefKind::AssocOpaqueTy
            | DefKind::TyParam => ns == Namespace::TypeNS,

            DefKind::Fn
            | DefKind::Const
            | DefKind::ConstParam
            | DefKind::Static
            | DefKind::Ctor(..)
            | DefKind::Method
            | DefKind::AssocConst => ns == Namespace::ValueNS,

            DefKind::Macro(..) => ns == Namespace::MacroNS,
        }
    }
}

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
pub enum Res<Id = hir::HirId> {
    Def(DefKind, DefId),

    // Type namespace
    PrimTy(hir::PrimTy),
    SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
    ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]`

    // Value namespace
    SelfCtor(DefId /* impl */), // `DefId` refers to the impl
    Local(Id),

    // Macro namespace
    NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]`

    // All namespaces
    Err,
}

/// The result of resolving a path before lowering to HIR,
/// with "module" segments resolved and associated item
/// segments deferred to type checking.
/// `base_res` is the resolution of the resolved part of the
/// path, `unresolved_segments` is the number of unresolved
/// segments.
///
/// ```text
/// module::Type::AssocX::AssocY::MethodOrAssocType
/// ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// base_res      unresolved_segments = 3
///
/// <T as Trait>::AssocX::AssocY::MethodOrAssocType
///       ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
///       base_res        unresolved_segments = 2
/// ```
#[derive(Copy, Clone, Debug)]
pub struct PartialRes {
    base_res: Res<NodeId>,
    unresolved_segments: usize,
}

impl PartialRes {
    #[inline]
    pub fn new(base_res: Res<NodeId>) -> Self {
        PartialRes { base_res, unresolved_segments: 0 }
    }

    #[inline]
    pub fn with_unresolved_segments(base_res: Res<NodeId>, mut unresolved_segments: usize) -> Self {
        if base_res == Res::Err {
            unresolved_segments = 0
        }
        PartialRes { base_res, unresolved_segments }
    }

    #[inline]
    pub fn base_res(&self) -> Res<NodeId> {
        self.base_res
    }

    #[inline]
    pub fn unresolved_segments(&self) -> usize {
        self.unresolved_segments
    }
}

/// Different kinds of symbols don't influence each other.
///
/// Therefore, they have a separate universe (namespace).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Namespace {
    TypeNS,
    ValueNS,
    MacroNS,
}

impl Namespace {
    pub fn descr(self) -> &'static str {
        match self {
            TypeNS => "type",
            ValueNS => "value",
            MacroNS => "macro",
        }
    }
}

/// Just a helper ‒ separate structure for each namespace.
#[derive(Copy, Clone, Default, Debug)]
pub struct PerNS<T> {
    pub value_ns: T,
    pub type_ns: T,
    pub macro_ns: T,
}

impl<T> PerNS<T> {
    pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> PerNS<U> {
        PerNS { value_ns: f(self.value_ns), type_ns: f(self.type_ns), macro_ns: f(self.macro_ns) }
    }
}

impl<T> ::std::ops::Index<Namespace> for PerNS<T> {
    type Output = T;

    fn index(&self, ns: Namespace) -> &T {
        match ns {
            ValueNS => &self.value_ns,
            TypeNS => &self.type_ns,
            MacroNS => &self.macro_ns,
        }
    }
}

impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> {
    fn index_mut(&mut self, ns: Namespace) -> &mut T {
        match ns {
            ValueNS => &mut self.value_ns,
            TypeNS => &mut self.type_ns,
            MacroNS => &mut self.macro_ns,
        }
    }
}

impl<T> PerNS<Option<T>> {
    /// Returns `true` if all the items in this collection are `None`.
    pub fn is_empty(&self) -> bool {
        self.type_ns.is_none() && self.value_ns.is_none() && self.macro_ns.is_none()
    }

    /// Returns an iterator over the items which are `Some`.
    pub fn present_items(self) -> impl Iterator<Item = T> {
        use std::iter::once;

        once(self.type_ns).chain(once(self.value_ns)).chain(once(self.macro_ns)).filter_map(|it| it)
    }
}

/// This is the replacement export map. It maps a module to all of the exports
/// within.
pub type ExportMap<Id> = DefIdMap<Vec<Export<Id>>>;

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
pub struct Export<Id> {
    /// The name of the target.
    pub ident: ast::Ident,
    /// The resolution of the target.
    pub res: Res<Id>,
    /// The span of the target.
    pub span: Span,
    /// The visibility of the export.
    /// We include non-`pub` exports for hygienic macros that get used from extern crates.
    pub vis: ty::Visibility,
}

impl<Id> Export<Id> {
    pub fn map_id<R>(self, map: impl FnMut(Id) -> R) -> Export<R> {
        Export { ident: self.ident, res: self.res.map_id(map), span: self.span, vis: self.vis }
    }
}

impl CtorKind {
    pub fn from_ast(vdata: &ast::VariantData) -> CtorKind {
        match *vdata {
            ast::VariantData::Tuple(..) => CtorKind::Fn,
            ast::VariantData::Unit(..) => CtorKind::Const,
            ast::VariantData::Struct(..) => CtorKind::Fictive,
        }
    }

    pub fn from_hir(vdata: &hir::VariantData<'_>) -> CtorKind {
        match *vdata {
            hir::VariantData::Tuple(..) => CtorKind::Fn,
            hir::VariantData::Unit(..) => CtorKind::Const,
            hir::VariantData::Struct(..) => CtorKind::Fictive,
        }
    }
}

impl NonMacroAttrKind {
    pub fn descr(self) -> &'static str {
        match self {
            NonMacroAttrKind::Builtin => "built-in attribute",
            NonMacroAttrKind::Tool => "tool attribute",
            NonMacroAttrKind::DeriveHelper => "derive helper attribute",
            NonMacroAttrKind::Registered => "explicitly registered attribute",
        }
    }

    pub fn article(self) -> &'static str {
        match self {
            NonMacroAttrKind::Registered => "an",
            _ => "a",
        }
    }

    /// Users of some attributes cannot mark them as used, so they are considered always used.
    pub fn is_used(self) -> bool {
        match self {
            NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper => true,
            NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered => false,
        }
    }
}

impl<Id> Res<Id> {
    /// Return the `DefId` of this `Def` if it has an ID, else panic.
    pub fn def_id(&self) -> DefId
    where
        Id: Debug,
    {
        self.opt_def_id().unwrap_or_else(|| bug!("attempted .def_id() on invalid res: {:?}", self))
    }

    /// Return `Some(..)` with the `DefId` of this `Res` if it has a ID, else `None`.
    pub fn opt_def_id(&self) -> Option<DefId> {
        match *self {
            Res::Def(_, id) => Some(id),

            Res::Local(..)
            | Res::PrimTy(..)
            | Res::SelfTy(..)
            | Res::SelfCtor(..)
            | Res::ToolMod
            | Res::NonMacroAttr(..)
            | Res::Err => None,
        }
    }

    /// Return the `DefId` of this `Res` if it represents a module.
    pub fn mod_def_id(&self) -> Option<DefId> {
        match *self {
            Res::Def(DefKind::Mod, id) => Some(id),
            _ => None,
        }
    }

    /// A human readable name for the res kind ("function", "module", etc.).
    pub fn descr(&self) -> &'static str {
        match *self {
            Res::Def(kind, def_id) => kind.descr(def_id),
            Res::SelfCtor(..) => "self constructor",
            Res::PrimTy(..) => "builtin type",
            Res::Local(..) => "local variable",
            Res::SelfTy(..) => "self type",
            Res::ToolMod => "tool module",
            Res::NonMacroAttr(attr_kind) => attr_kind.descr(),
            Res::Err => "unresolved item",
        }
    }

    /// Gets an English article for the `Res`.
    pub fn article(&self) -> &'static str {
        match *self {
            Res::Def(kind, _) => kind.article(),
            Res::NonMacroAttr(kind) => kind.article(),
            Res::Err => "an",
            _ => "a",
        }
    }

    pub fn map_id<R>(self, mut map: impl FnMut(Id) -> R) -> Res<R> {
        match self {
            Res::Def(kind, id) => Res::Def(kind, id),
            Res::SelfCtor(id) => Res::SelfCtor(id),
            Res::PrimTy(id) => Res::PrimTy(id),
            Res::Local(id) => Res::Local(map(id)),
            Res::SelfTy(a, b) => Res::SelfTy(a, b),
            Res::ToolMod => Res::ToolMod,
            Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
            Res::Err => Res::Err,
        }
    }

    pub fn macro_kind(self) -> Option<MacroKind> {
        match self {
            Res::Def(DefKind::Macro(kind), _) => Some(kind),
            Res::NonMacroAttr(..) => Some(MacroKind::Attr),
            _ => None,
        }
    }

    pub fn matches_ns(&self, ns: Namespace) -> bool {
        match self {
            Res::Def(kind, ..) => kind.matches_ns(ns),
            Res::PrimTy(..) | Res::SelfTy(..) | Res::ToolMod => ns == Namespace::TypeNS,
            Res::SelfCtor(..) | Res::Local(..) => ns == Namespace::ValueNS,
            Res::NonMacroAttr(..) => ns == Namespace::MacroNS,
            Res::Err => true,
        }
    }
}
<commit_msg>simplify self::Namespace::* import<commit_after>use crate::hir;
use crate::hir::def_id::{DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
use crate::ty;

use rustc_macros::HashStable;
use rustc_span::hygiene::MacroKind;
use rustc_span::Span;
use syntax::ast;
use syntax::ast::NodeId;

use std::fmt::Debug;

/// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct.
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
pub enum CtorOf {
    /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit struct.
    Struct,
    /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit variant.
    Variant,
}

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
pub enum CtorKind {
    /// Constructor function automatically created by a tuple struct/variant.
    Fn,
    /// Constructor constant automatically created by a unit struct/variant.
    Const,
    /// Unusable name in value namespace created by a struct variant.
    Fictive,
}

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
pub enum NonMacroAttrKind {
    /// Single-segment attribute defined by the language (`#[inline]`)
    Builtin,
    /// Multi-segment custom attribute living in a "tool module" (`#[rustfmt::skip]`).
    Tool,
    /// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`).
    DeriveHelper,
    /// Single-segment custom attribute registered with `#[register_attr]`.
    Registered,
}

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
pub enum DefKind {
    // Type namespace
    Mod,
    /// Refers to the struct itself, `DefKind::Ctor` refers to its constructor if it exists.
    Struct,
    Union,
    Enum,
    /// Refers to the variant itself, `DefKind::Ctor` refers to its constructor if it exists.
    Variant,
    Trait,
    /// `type Foo = impl Bar;`
    OpaqueTy,
    /// `type Foo = Bar;`
    TyAlias,
    ForeignTy,
    TraitAlias,
    AssocTy,
    /// `type Foo = impl Bar;`
    AssocOpaqueTy,
    TyParam,

    // Value namespace
    Fn,
    Const,
    ConstParam,
    Static,
    /// Refers to the struct or enum variant's constructor.
    Ctor(CtorOf, CtorKind),
    Method,
    AssocConst,

    // Macro namespace
    Macro(MacroKind),
}

impl DefKind {
    pub fn descr(self, def_id: DefId) -> &'static str {
        match self {
            DefKind::Fn => "function",
            DefKind::Mod if def_id.index == CRATE_DEF_INDEX && def_id.krate != LOCAL_CRATE => {
                "crate"
            }
            DefKind::Mod => "module",
            DefKind::Static => "static",
            DefKind::Enum => "enum",
            DefKind::Variant => "variant",
            DefKind::Ctor(CtorOf::Variant, CtorKind::Fn) => "tuple variant",
            DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => "unit variant",
            DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive) => "struct variant",
            DefKind::Struct => "struct",
            DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct",
            DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct",
            DefKind::Ctor(CtorOf::Struct, CtorKind::Fictive) => {
                bug!("impossible struct constructor")
            }
            DefKind::OpaqueTy => "opaque type",
            DefKind::TyAlias => "type alias",
            DefKind::TraitAlias => "trait alias",
            DefKind::AssocTy => "associated type",
            DefKind::AssocOpaqueTy => "associated opaque type",
            DefKind::Union => "union",
            DefKind::Trait => "trait",
            DefKind::ForeignTy => "foreign type",
            DefKind::Method => "method",
            DefKind::Const => "constant",
            DefKind::AssocConst => "associated constant",
            DefKind::TyParam => "type parameter",
            DefKind::ConstParam => "const parameter",
            DefKind::Macro(macro_kind) => macro_kind.descr(),
        }
    }

    /// Gets an English article for the definition.
    pub fn article(&self) -> &'static str {
        match *self {
            DefKind::AssocTy
            | DefKind::AssocConst
            | DefKind::AssocOpaqueTy
            | DefKind::Enum
            | DefKind::OpaqueTy => "an",
            DefKind::Macro(macro_kind) => macro_kind.article(),
            _ => "a",
        }
    }

    pub fn matches_ns(&self, ns: Namespace) -> bool {
        match self {
            DefKind::Mod
            | DefKind::Struct
            | DefKind::Union
            | DefKind::Enum
            | DefKind::Variant
            | DefKind::Trait
            | DefKind::OpaqueTy
            | DefKind::TyAlias
            | DefKind::ForeignTy
            | DefKind::TraitAlias
            | DefKind::AssocTy
            | DefKind::AssocOpaqueTy
            | DefKind::TyParam => ns == Namespace::TypeNS,

            DefKind::Fn
            | DefKind::Const
            | DefKind::ConstParam
            | DefKind::Static
            | DefKind::Ctor(..)
            | DefKind::Method
            | DefKind::AssocConst => ns == Namespace::ValueNS,

            DefKind::Macro(..) => ns == Namespace::MacroNS,
        }
    }
}

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
pub enum Res<Id = hir::HirId> {
    Def(DefKind, DefId),

    // Type namespace
    PrimTy(hir::PrimTy),
    SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
    ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]`

    // Value namespace
    SelfCtor(DefId /* impl */), // `DefId` refers to the impl
    Local(Id),

    // Macro namespace
    NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]`

    // All namespaces
    Err,
}

/// The result of resolving a path before lowering to HIR,
/// with "module" segments resolved and associated item
/// segments deferred to type checking.
/// `base_res` is the resolution of the resolved part of the
/// path, `unresolved_segments` is the number of unresolved
/// segments.
///
/// ```text
/// module::Type::AssocX::AssocY::MethodOrAssocType
/// ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// base_res      unresolved_segments = 3
///
/// <T as Trait>::AssocX::AssocY::MethodOrAssocType
///       ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
///       base_res        unresolved_segments = 2
/// ```
#[derive(Copy, Clone, Debug)]
pub struct PartialRes {
    base_res: Res<NodeId>,
    unresolved_segments: usize,
}

impl PartialRes {
    #[inline]
    pub fn new(base_res: Res<NodeId>) -> Self {
        PartialRes { base_res, unresolved_segments: 0 }
    }

    #[inline]
    pub fn with_unresolved_segments(base_res: Res<NodeId>, mut unresolved_segments: usize) -> Self {
        if base_res == Res::Err {
            unresolved_segments = 0
        }
        PartialRes { base_res, unresolved_segments }
    }

    #[inline]
    pub fn base_res(&self) -> Res<NodeId> {
        self.base_res
    }

    #[inline]
    pub fn unresolved_segments(&self) -> usize {
        self.unresolved_segments
    }
}

/// Different kinds of symbols don't influence each other.
///
/// Therefore, they have a separate universe (namespace).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Namespace {
    TypeNS,
    ValueNS,
    MacroNS,
}

impl Namespace {
    pub fn descr(self) -> &'static str {
        match self {
            Self::TypeNS => "type",
            Self::ValueNS => "value",
            Self::MacroNS => "macro",
        }
    }
}

/// Just a helper ‒ separate structure for each namespace.
#[derive(Copy, Clone, Default, Debug)]
pub struct PerNS<T> {
    pub value_ns: T,
    pub type_ns: T,
    pub macro_ns: T,
}

impl<T> PerNS<T> {
    pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> PerNS<U> {
        PerNS { value_ns: f(self.value_ns), type_ns: f(self.type_ns), macro_ns: f(self.macro_ns) }
    }
}

impl<T> ::std::ops::Index<Namespace> for PerNS<T> {
    type Output = T;

    fn index(&self, ns: Namespace) -> &T {
        match ns {
            Namespace::ValueNS => &self.value_ns,
            Namespace::TypeNS => &self.type_ns,
            Namespace::MacroNS => &self.macro_ns,
        }
    }
}

impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> {
    fn index_mut(&mut self, ns: Namespace) -> &mut T {
        match ns {
            Namespace::ValueNS => &mut self.value_ns,
            Namespace::TypeNS => &mut self.type_ns,
            Namespace::MacroNS => &mut self.macro_ns,
        }
    }
}

impl<T> PerNS<Option<T>> {
    /// Returns `true` if all the items in this collection are `None`.
    pub fn is_empty(&self) -> bool {
        self.type_ns.is_none() && self.value_ns.is_none() && self.macro_ns.is_none()
    }

    /// Returns an iterator over the items which are `Some`.
    pub fn present_items(self) -> impl Iterator<Item = T> {
        use std::iter::once;

        once(self.type_ns).chain(once(self.value_ns)).chain(once(self.macro_ns)).filter_map(|it| it)
    }
}

/// This is the replacement export map. It maps a module to all of the exports
/// within.
pub type ExportMap<Id> = DefIdMap<Vec<Export<Id>>>;

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
pub struct Export<Id> {
    /// The name of the target.
    pub ident: ast::Ident,
    /// The resolution of the target.
    pub res: Res<Id>,
    /// The span of the target.
    pub span: Span,
    /// The visibility of the export.
    /// We include non-`pub` exports for hygienic macros that get used from extern crates.
    pub vis: ty::Visibility,
}

impl<Id> Export<Id> {
    pub fn map_id<R>(self, map: impl FnMut(Id) -> R) -> Export<R> {
        Export { ident: self.ident, res: self.res.map_id(map), span: self.span, vis: self.vis }
    }
}

impl CtorKind {
    pub fn from_ast(vdata: &ast::VariantData) -> CtorKind {
        match *vdata {
            ast::VariantData::Tuple(..) => CtorKind::Fn,
            ast::VariantData::Unit(..) => CtorKind::Const,
            ast::VariantData::Struct(..) => CtorKind::Fictive,
        }
    }

    pub fn from_hir(vdata: &hir::VariantData<'_>) -> CtorKind {
        match *vdata {
            hir::VariantData::Tuple(..) => CtorKind::Fn,
            hir::VariantData::Unit(..) => CtorKind::Const,
            hir::VariantData::Struct(..) => CtorKind::Fictive,
        }
    }
}

impl NonMacroAttrKind {
    pub fn descr(self) -> &'static str {
        match self {
            NonMacroAttrKind::Builtin => "built-in attribute",
            NonMacroAttrKind::Tool => "tool attribute",
            NonMacroAttrKind::DeriveHelper => "derive helper attribute",
            NonMacroAttrKind::Registered => "explicitly registered attribute",
        }
    }

    pub fn article(self) -> &'static str {
        match self {
            NonMacroAttrKind::Registered => "an",
            _ => "a",
        }
    }

    /// Users of some attributes cannot mark them as used, so they are considered always used.
    pub fn is_used(self) -> bool {
        match self {
            NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper => true,
            NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered => false,
        }
    }
}

impl<Id> Res<Id> {
    /// Return the `DefId` of this `Def` if it has an ID, else panic.
    pub fn def_id(&self) -> DefId
    where
        Id: Debug,
    {
        self.opt_def_id().unwrap_or_else(|| bug!("attempted .def_id() on invalid res: {:?}", self))
    }

    /// Return `Some(..)` with the `DefId` of this `Res` if it has a ID, else `None`.
    pub fn opt_def_id(&self) -> Option<DefId> {
        match *self {
            Res::Def(_, id) => Some(id),

            Res::Local(..)
            | Res::PrimTy(..)
            | Res::SelfTy(..)
            | Res::SelfCtor(..)
            | Res::ToolMod
            | Res::NonMacroAttr(..)
            | Res::Err => None,
        }
    }

    /// Return the `DefId` of this `Res` if it represents a module.
    pub fn mod_def_id(&self) -> Option<DefId> {
        match *self {
            Res::Def(DefKind::Mod, id) => Some(id),
            _ => None,
        }
    }

    /// A human readable name for the res kind ("function", "module", etc.).
    pub fn descr(&self) -> &'static str {
        match *self {
            Res::Def(kind, def_id) => kind.descr(def_id),
            Res::SelfCtor(..) => "self constructor",
            Res::PrimTy(..) => "builtin type",
            Res::Local(..) => "local variable",
            Res::SelfTy(..) => "self type",
            Res::ToolMod => "tool module",
            Res::NonMacroAttr(attr_kind) => attr_kind.descr(),
            Res::Err => "unresolved item",
        }
    }

    /// Gets an English article for the `Res`.
    pub fn article(&self) -> &'static str {
        match *self {
            Res::Def(kind, _) => kind.article(),
            Res::NonMacroAttr(kind) => kind.article(),
            Res::Err => "an",
            _ => "a",
        }
    }

    pub fn map_id<R>(self, mut map: impl FnMut(Id) -> R) -> Res<R> {
        match self {
            Res::Def(kind, id) => Res::Def(kind, id),
            Res::SelfCtor(id) => Res::SelfCtor(id),
            Res::PrimTy(id) => Res::PrimTy(id),
            Res::Local(id) => Res::Local(map(id)),
            Res::SelfTy(a, b) => Res::SelfTy(a, b),
            Res::ToolMod => Res::ToolMod,
            Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
            Res::Err => Res::Err,
        }
    }

    pub fn macro_kind(self) -> Option<MacroKind> {
        match self {
            Res::Def(DefKind::Macro(kind), _) => Some(kind),
            Res::NonMacroAttr(..) => Some(MacroKind::Attr),
            _ => None,
        }
    }

    pub fn matches_ns(&self, ns: Namespace) -> bool {
        match self {
            Res::Def(kind, ..) => kind.matches_ns(ns),
            Res::PrimTy(..) | Res::SelfTy(..) | Res::ToolMod => ns == Namespace::TypeNS,
            Res::SelfCtor(..) | Res::Local(..) => ns == Namespace::ValueNS,
            Res::NonMacroAttr(..) => ns == Namespace::MacroNS,
            Res::Err => true,
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt;

#[derive(Clone, Debug, PartialEq)]
pub struct Author {
  pub name: String,
  pub email: String,
}

pub struct AuthorParser {
  pub domain: String,
}

impl AuthorParser {
  // NOTE This doesn't check domain at all.
  pub fn parse(&self, raw: &str) -> Option<Author> {
    let mut split = raw.split(';').map(str::trim);

    let name = match split.next() {
      Some(name) if !name.is_empty() => name,
      _ => {
        return None;
      }
    };

    let email_seed = match split.next() {
      Some(email_seed) if !email_seed.is_empty() => email_seed,
      _ => {
        return None;
      }
    };

    let email = if email_seed.contains('@') {
      email_seed.into()
    } else {
      format!("{}@{}", email_seed, self.domain)
    };

    Some(Author {
      name: name.into(),
      email: email,
    })
  }
}

impl fmt::Display for Author {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{} <{}>", self.name, self.email)
  }
}

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

  #[test]
  fn new() {
    let author_parser = AuthorParser { domain: "example.com".into() };

    let author = author_parser.parse("Jane Doe; jdoe").unwrap();
    assert_eq!(author.name, "Jane Doe");
    assert_eq!(author.email, "jdoe@example.com");

    let author = author_parser.parse("");
    assert!(author.is_none());

    let author = author_parser.parse("Jane Doe");
    assert!(author.is_none());

    let author = author_parser.parse("Jane Doe; ");
    assert!(author.is_none());

    let author = author_parser.parse("Jane Doe; jane.doe@example.edu").unwrap();
    assert_eq!(author.name, "Jane Doe");
    assert_eq!(author.email, "jane.doe@example.edu");
  }
}
<commit_msg>remove comment about domain<commit_after>use std::fmt;

#[derive(Clone, Debug, PartialEq)]
pub struct Author {
  pub name: String,
  pub email: String,
}

pub struct AuthorParser {
  pub domain: String,
}

impl AuthorParser {
  pub fn parse(&self, raw: &str) -> Option<Author> {
    let mut split = raw.split(';').map(str::trim);

    let name = match split.next() {
      Some(name) if !name.is_empty() => name,
      _ => {
        return None;
      }
    };

    let email_seed = match split.next() {
      Some(email_seed) if !email_seed.is_empty() => email_seed,
      _ => {
        return None;
      }
    };

    let email = if email_seed.contains('@') {
      email_seed.into()
    } else {
      format!("{}@{}", email_seed, self.domain)
    };

    Some(Author {
      name: name.into(),
      email: email,
    })
  }
}

impl fmt::Display for Author {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{} <{}>", self.name, self.email)
  }
}

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

  #[test]
  fn new() {
    let author_parser = AuthorParser { domain: "example.com".into() };

    let author = author_parser.parse("Jane Doe; jdoe").unwrap();
    assert_eq!(author.name, "Jane Doe");
    assert_eq!(author.email, "jdoe@example.com");

    let author = author_parser.parse("");
    assert!(author.is_none());

    let author = author_parser.parse("Jane Doe");
    assert!(author.is_none());

    let author = author_parser.parse("Jane Doe; ");
    assert!(author.is_none());

    let author = author_parser.parse("Jane Doe; jane.doe@example.edu").unwrap();
    assert_eq!(author.name, "Jane Doe");
    assert_eq!(author.email, "jane.doe@example.edu");
  }
}
<|endoftext|>


<commit_before>
extern crate rustc_serialize;

/// GeoIP2 Country record
#[derive(RustcDecodable, Debug)]
pub struct Country {
    pub continent: Option<model::Continent>,
    pub country: Option<model::Country>,
    pub registered_country: Option<model::Country>,
    pub represented_country: Option<model::RepresentedCountry>,
    pub traits: Option<model::Traits>,
}

/// GeoIP2 City record
#[derive(RustcDecodable, Debug)]
pub struct City {
    pub city: Option<model::City>,
    pub continent: Option<model::Continent>,
    pub country: Option<model::Country>,
    pub location: Option<model::Location>,
    pub postal: Option<model::Postal>,
    pub registered_country: Option<model::Country>,
    pub represented_country: Option<model::RepresentedCountry>,
    pub subdivisions: Option<Vec<model::Subdivision>>,
    pub traits: Option<model::Traits>,
}

pub mod model {
    use std::collections::BTreeMap;

    #[derive(RustcDecodable, Debug)]
    pub struct City {
        pub geoname_id: Option<u32>,
        pub names: Option<BTreeMap<String, String>>,
    }

    #[derive(RustcDecodable, Debug)]
    pub struct Continent {
        pub code: Option<String>,
        pub geoname_id: Option<u32>,
        pub names: Option<BTreeMap<String, String>>,
    }

    #[derive(RustcDecodable, Debug)]
    pub struct Country {
        pub geoname_id: Option<u32>,
        pub iso_code: Option<String>,
        pub names: Option<BTreeMap<String, String>>,
    }

    #[derive(RustcDecodable, Debug)]
    pub struct Location {
        pub latitude: Option<f64>,
        pub longitude: Option<f64>,
        pub metro_code: Option<u16>,
        pub time_zone: Option<String>,
    }

    #[derive(RustcDecodable, Debug)]
    pub struct Postal {
        pub code: Option<String>,
    }

    #[derive(RustcDecodable, Debug)]
    pub struct RepresentedCountry {
        pub geoname_id: Option<u32>,
        pub iso_code: Option<String>,
        pub names: Option<BTreeMap<String, String>>,
        // pub type: Option<String>,
    }

    #[derive(RustcDecodable, Debug)]
    pub struct Subdivision {
        pub geoname_id: Option<u32>,
        pub iso_code: Option<String>,
        pub names: Option<BTreeMap<String, String>>,
    }

    #[derive(RustcDecodable, Debug)]
    pub struct Traits {
        pub is_anonymous_proxy: Option<bool>,
        pub is_satellite_provider: Option<bool>,
    }
}
<commit_msg>Mising structures<commit_after>
extern crate rustc_serialize;

/// GeoIP2 Country record
#[derive(RustcDecodable, Debug)]
pub struct Country {
    pub continent: Option<model::Continent>,
    pub country: Option<model::Country>,
    pub registered_country: Option<model::Country>,
    pub represented_country: Option<model::RepresentedCountry>,
    pub traits: Option<model::Traits>,
}

/// GeoIP2 City record
#[derive(RustcDecodable, Debug)]
pub struct City {
    pub city: Option<model::City>,
    pub continent: Option<model::Continent>,
    pub country: Option<model::Country>,
    pub location: Option<model::Location>,
    pub postal: Option<model::Postal>,
    pub registered_country: Option<model::Country>,
    pub represented_country: Option<model::RepresentedCountry>,
    pub subdivisions: Option<Vec<model::Subdivision>>,
    pub traits: Option<model::Traits>,
}

/// GeoIP2 ISP record
#[derive(RustcDecodable, Debug)]
pub struct Isp {
    pub autonomous_system_number: Option<u32>,
    pub autonomous_system_organization: Option<String>,
    pub isp: Option<String>,
    pub organization: Option<String>,
}

/// GeoIP2 Connection-Type record
#[derive(RustcDecodable, Debug)]
pub struct ConnectionType {
    pub connection_type: Option<String>,
}

/// GeoIP2 Anonymous Ip record
#[derive(RustcDecodable, Debug)]
pub struct AnonymousIp {
    pub is_anonymous: Option<bool>,
    pub is_public_proxy: Option<bool>
}

pub mod model {
    use std::collections::BTreeMap;

    #[derive(RustcDecodable, Debug)]
    pub struct City {
        pub geoname_id: Option<u32>,
        pub names: Option<BTreeMap<String, String>>,
    }

    #[derive(RustcDecodable, Debug)]
    pub struct Continent {
        pub code: Option<String>,
        pub geoname_id: Option<u32>,
        pub names: Option<BTreeMap<String, String>>,
    }

    #[derive(RustcDecodable, Debug)]
    pub struct Country {
        pub geoname_id: Option<u32>,
        pub iso_code: Option<String>,
        pub names: Option<BTreeMap<String, String>>,
    }

    #[derive(RustcDecodable, Debug)]
    pub struct Location {
        pub latitude: Option<f64>,
        pub longitude: Option<f64>,
        pub metro_code: Option<u16>,
        pub time_zone: Option<String>,
    }

    #[derive(RustcDecodable, Debug)]
    pub struct Postal {
        pub code: Option<String>,
    }

    #[derive(RustcDecodable, Debug)]
    pub struct RepresentedCountry {
        pub geoname_id: Option<u32>,
        pub iso_code: Option<String>,
        pub names: Option<BTreeMap<String, String>>,
        // pub type: Option<String>,
    }

    #[derive(RustcDecodable, Debug)]
    pub struct Subdivision {
        pub geoname_id: Option<u32>,
        pub iso_code: Option<String>,
        pub names: Option<BTreeMap<String, String>>,
    }

    #[derive(RustcDecodable, Debug)]
    pub struct Traits {
        pub is_anonymous_proxy: Option<bool>,
        pub is_satellite_provider: Option<bool>,
    }
}
<|endoftext|>


<commit_before>//! A stably addressed token buffer supporting efficient traversal based on a
//! cheaply copyable cursor.
//!
//! *This module is available if Syn is built with the `"parsing"` feature.*

// This module is heavily commented as it contains most of the unsafe code in
// Syn, and caution should be used when editing it. The public-facing interface
// is 100% safe but the implementation is fragile internally.

#[cfg(all(
    not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
    feature = "proc-macro"
))]
use crate::proc_macro as pm;
use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};

use std::marker::PhantomData;
use std::ptr;

use crate::Lifetime;

/// Internal type which is used instead of `TokenTree` to represent a token tree
/// within a `TokenBuffer`.
enum Entry {
    // Mimicking types from proc-macro.
    Group(Group, TokenBuffer),
    Ident(Ident),
    Punct(Punct),
    Literal(Literal),
    // End entries contain a raw pointer to the entry from the containing
    // token tree, or null if this is the outermost level.
    End(*const Entry),
}

/// A buffer that can be efficiently traversed multiple times, unlike
/// `TokenStream` which requires a deep copy in order to traverse more than
/// once.
///
/// *This type is available if Syn is built with the `"parsing"` feature.*
pub struct TokenBuffer {
    // NOTE: Do not derive clone on this - there are raw pointers inside which
    // will be messed up. Moving the `TokenBuffer` itself is safe as the actual
    // backing slices won't be moved.
    data: Box<[Entry]>,
}

impl TokenBuffer {
    // NOTE: DO NOT MUTATE THE `Vec` RETURNED FROM THIS FUNCTION ONCE IT
    // RETURNS, THE ADDRESS OF ITS BACKING MEMORY MUST REMAIN STABLE.
    fn inner_new(stream: TokenStream, up: *const Entry) -> TokenBuffer {
        // Build up the entries list, recording the locations of any Groups
        // in the list to be processed later.
        let mut entries = Vec::new();
        let mut seqs = Vec::new();
        for tt in stream {
            match tt {
                TokenTree::Ident(sym) => {
                    entries.push(Entry::Ident(sym));
                }
                TokenTree::Punct(op) => {
                    entries.push(Entry::Punct(op));
                }
                TokenTree::Literal(l) => {
                    entries.push(Entry::Literal(l));
                }
                TokenTree::Group(g) => {
                    // Record the index of the interesting entry, and store an
                    // `End(null)` there temporarially.
                    seqs.push((entries.len(), g));
                    entries.push(Entry::End(ptr::null()));
                }
            }
        }
        // Add an `End` entry to the end with a reference to the enclosing token
        // stream which was passed in.
        entries.push(Entry::End(up));

        // NOTE: This is done to ensure that we don't accidentally modify the
        // length of the backing buffer. The backing buffer must remain at a
        // constant address after this point, as we are going to store a raw
        // pointer into it.
        let mut entries = entries.into_boxed_slice();
        for (idx, group) in seqs {
            // We know that this index refers to one of the temporary
            // `End(null)` entries, and we know that the last entry is
            // `End(up)`, so the next index is also valid.
            let seq_up = &entries[idx + 1] as *const Entry;

            // The end entry stored at the end of this Entry::Group should
            // point to the Entry which follows the Group in the list.
            let inner = Self::inner_new(group.stream(), seq_up);
            entries[idx] = Entry::Group(group, inner);
        }

        TokenBuffer { data: entries }
    }

    /// Creates a `TokenBuffer` containing all the tokens from the input
    /// `TokenStream`.
    ///
    /// *This method is available if Syn is built with both the `"parsing"` and
    /// `"proc-macro"` features.*
    #[cfg(all(
        not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
        feature = "proc-macro"
    ))]
    pub fn new(stream: pm::TokenStream) -> TokenBuffer {
        Self::new2(stream.into())
    }

    /// Creates a `TokenBuffer` containing all the tokens from the input
    /// `TokenStream`.
    pub fn new2(stream: TokenStream) -> TokenBuffer {
        Self::inner_new(stream, ptr::null())
    }

    /// Creates a cursor referencing the first token in the buffer and able to
    /// traverse until the end of the buffer.
    pub fn begin(&self) -> Cursor {
        unsafe { Cursor::create(&self.data[0], &self.data[self.data.len() - 1]) }
    }
}

/// A cheaply copyable cursor into a `TokenBuffer`.
///
/// This cursor holds a shared reference into the immutable data which is used
/// internally to represent a `TokenStream`, and can be efficiently manipulated
/// and copied around.
///
/// An empty `Cursor` can be created directly, or one may create a `TokenBuffer`
/// object and get a cursor to its first token with `begin()`.
///
/// Two cursors are equal if they have the same location in the same input
/// stream, and have the same scope.
///
/// *This type is available if Syn is built with the `"parsing"` feature.*
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Cursor<'a> {
    // The current entry which the `Cursor` is pointing at.
    ptr: *const Entry,
    // This is the only `Entry::End(..)` object which this cursor is allowed to
    // point at. All other `End` objects are skipped over in `Cursor::create`.
    scope: *const Entry,
    // Cursor is covariant in 'a. This field ensures that our pointers are still
    // valid.
    marker: PhantomData<&'a Entry>,
}

impl<'a> Cursor<'a> {
    /// Creates a cursor referencing a static empty TokenStream.
    pub fn empty() -> Self {
        // It's safe in this situation for us to put an `Entry` object in global
        // storage, despite it not actually being safe to send across threads
        // (`Ident` is a reference into a thread-local table). This is because
        // this entry never includes a `Ident` object.
        //
        // This wrapper struct allows us to break the rules and put a `Sync`
        // object in global storage.
        struct UnsafeSyncEntry(Entry);
        unsafe impl Sync for UnsafeSyncEntry {}
        static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End(0 as *const Entry));

        Cursor {
            ptr: &EMPTY_ENTRY.0,
            scope: &EMPTY_ENTRY.0,
            marker: PhantomData,
        }
    }

    /// This create method intelligently exits non-explicitly-entered
    /// `None`-delimited scopes when the cursor reaches the end of them,
    /// allowing for them to be treated transparently.
    unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self {
        // NOTE: If we're looking at a `End(..)`, we want to advance the cursor
        // past it, unless `ptr == scope`, which means that we're at the edge of
        // our cursor's scope. We should only have `ptr != scope` at the exit
        // from None-delimited groups entered with `ignore_none`.
        while let Entry::End(exit) = *ptr {
            if ptr == scope {
                break;
            }
            ptr = exit;
        }

        Cursor {
            ptr,
            scope,
            marker: PhantomData,
        }
    }

    /// Get the current entry.
    fn entry(self) -> &'a Entry {
        unsafe { &*self.ptr }
    }

    /// Bump the cursor to point at the next token after the current one. This
    /// is undefined behavior if the cursor is currently looking at an
    /// `Entry::End`.
    unsafe fn bump(self) -> Cursor<'a> {
        Cursor::create(self.ptr.offset(1), self.scope)
    }

    /// If the cursor is looking at a `None`-delimited group, move it to look at
    /// the first token inside instead. If the group is empty, this will move
    /// the cursor past the `None`-delimited group.
    ///
    /// WARNING: This mutates its argument.
    fn ignore_none(&mut self) {
        if let Entry::Group(group, buf) = self.entry() {
            if group.delimiter() == Delimiter::None {
                // NOTE: We call `Cursor::create` here to make sure that
                // situations where we should immediately exit the span after
                // entering it are handled correctly.
                unsafe {
                    *self = Cursor::create(&buf.data[0], self.scope);
                }
            }
        }
    }

    /// Checks whether the cursor is currently pointing at the end of its valid
    /// scope.
    #[inline]
    pub fn eof(self) -> bool {
        // We're at eof if we're at the end of our scope.
        self.ptr == self.scope
    }

    /// If the cursor is pointing at a `Group` with the given delimiter, returns
    /// a cursor into that group and one pointing to the next `TokenTree`.
    pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, Span, Cursor<'a>)> {
        // If we're not trying to enter a none-delimited group, we want to
        // ignore them. We have to make sure to _not_ ignore them when we want
        // to enter them, of course. For obvious reasons.
        if delim != Delimiter::None {
            self.ignore_none();
        }

        if let Entry::Group(group, buf) = self.entry() {
            if group.delimiter() == delim {
                return Some((buf.begin(), group.span(), unsafe { self.bump() }));
            }
        }

        None
    }

    /// If the cursor is pointing at a `Ident`, returns it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn ident(mut self) -> Option<(Ident, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Ident(ident) => Some((ident.clone(), unsafe { self.bump() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at an `Punct`, returns it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn punct(mut self) -> Option<(Punct, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Punct(op) if op.as_char() != '\'' => Some((op.clone(), unsafe { self.bump() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Literal`, return it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn literal(mut self) -> Option<(Literal, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Literal(lit) => Some((lit.clone(), unsafe { self.bump() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Lifetime`, returns it along with a
    /// cursor pointing at the next `TokenTree`.
    pub fn lifetime(mut self) -> Option<(Lifetime, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Punct(op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => {
                let next = unsafe { self.bump() };
                match next.ident() {
                    Some((ident, rest)) => {
                        let lifetime = Lifetime {
                            apostrophe: op.span(),
                            ident,
                        };
                        Some((lifetime, rest))
                    }
                    None => None,
                }
            }
            _ => None,
        }
    }

    /// Copies all remaining tokens visible from this cursor into a
    /// `TokenStream`.
    pub fn token_stream(self) -> TokenStream {
        let mut tts = Vec::new();
        let mut cursor = self;
        while let Some((tt, rest)) = cursor.token_tree() {
            tts.push(tt);
            cursor = rest;
        }
        tts.into_iter().collect()
    }

    /// If the cursor is pointing at a `TokenTree`, returns it along with a
    /// cursor pointing at the next `TokenTree`.
    ///
    /// Returns `None` if the cursor has reached the end of its stream.
    ///
    /// This method does not treat `None`-delimited groups as transparent, and
    /// will return a `Group(None, ..)` if the cursor is looking at one.
    pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> {
        let tree = match self.entry() {
            Entry::Group(group, _) => group.clone().into(),
            Entry::Literal(lit) => lit.clone().into(),
            Entry::Ident(ident) => ident.clone().into(),
            Entry::Punct(op) => op.clone().into(),
            Entry::End(..) => {
                return None;
            }
        };

        Some((tree, unsafe { self.bump() }))
    }

    /// Returns the `Span` of the current token, or `Span::call_site()` if this
    /// cursor points to eof.
    pub fn span(self) -> Span {
        match self.entry() {
            Entry::Group(group, _) => group.span(),
            Entry::Literal(l) => l.span(),
            Entry::Ident(t) => t.span(),
            Entry::Punct(o) => o.span(),
            Entry::End(..) => Span::call_site(),
        }
    }
}

pub(crate) fn same_scope(a: Cursor, b: Cursor) -> bool {
    a.scope == b.scope
}

pub(crate) fn open_span_of_group(cursor: Cursor) -> Span {
    match cursor.entry() {
        Entry::Group(group, _) => group.span_open(),
        _ => cursor.span(),
    }
}

pub(crate) fn close_span_of_group(cursor: Cursor) -> Span {
    match cursor.entry() {
        Entry::Group(group, _) => group.span_close(),
        _ => cursor.span(),
    }
}
<commit_msg>Remove unimportant inline attribute<commit_after>//! A stably addressed token buffer supporting efficient traversal based on a
//! cheaply copyable cursor.
//!
//! *This module is available if Syn is built with the `"parsing"` feature.*

// This module is heavily commented as it contains most of the unsafe code in
// Syn, and caution should be used when editing it. The public-facing interface
// is 100% safe but the implementation is fragile internally.

#[cfg(all(
    not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
    feature = "proc-macro"
))]
use crate::proc_macro as pm;
use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};

use std::marker::PhantomData;
use std::ptr;

use crate::Lifetime;

/// Internal type which is used instead of `TokenTree` to represent a token tree
/// within a `TokenBuffer`.
enum Entry {
    // Mimicking types from proc-macro.
    Group(Group, TokenBuffer),
    Ident(Ident),
    Punct(Punct),
    Literal(Literal),
    // End entries contain a raw pointer to the entry from the containing
    // token tree, or null if this is the outermost level.
    End(*const Entry),
}

/// A buffer that can be efficiently traversed multiple times, unlike
/// `TokenStream` which requires a deep copy in order to traverse more than
/// once.
///
/// *This type is available if Syn is built with the `"parsing"` feature.*
pub struct TokenBuffer {
    // NOTE: Do not derive clone on this - there are raw pointers inside which
    // will be messed up. Moving the `TokenBuffer` itself is safe as the actual
    // backing slices won't be moved.
    data: Box<[Entry]>,
}

impl TokenBuffer {
    // NOTE: DO NOT MUTATE THE `Vec` RETURNED FROM THIS FUNCTION ONCE IT
    // RETURNS, THE ADDRESS OF ITS BACKING MEMORY MUST REMAIN STABLE.
    fn inner_new(stream: TokenStream, up: *const Entry) -> TokenBuffer {
        // Build up the entries list, recording the locations of any Groups
        // in the list to be processed later.
        let mut entries = Vec::new();
        let mut seqs = Vec::new();
        for tt in stream {
            match tt {
                TokenTree::Ident(sym) => {
                    entries.push(Entry::Ident(sym));
                }
                TokenTree::Punct(op) => {
                    entries.push(Entry::Punct(op));
                }
                TokenTree::Literal(l) => {
                    entries.push(Entry::Literal(l));
                }
                TokenTree::Group(g) => {
                    // Record the index of the interesting entry, and store an
                    // `End(null)` there temporarially.
                    seqs.push((entries.len(), g));
                    entries.push(Entry::End(ptr::null()));
                }
            }
        }
        // Add an `End` entry to the end with a reference to the enclosing token
        // stream which was passed in.
        entries.push(Entry::End(up));

        // NOTE: This is done to ensure that we don't accidentally modify the
        // length of the backing buffer. The backing buffer must remain at a
        // constant address after this point, as we are going to store a raw
        // pointer into it.
        let mut entries = entries.into_boxed_slice();
        for (idx, group) in seqs {
            // We know that this index refers to one of the temporary
            // `End(null)` entries, and we know that the last entry is
            // `End(up)`, so the next index is also valid.
            let seq_up = &entries[idx + 1] as *const Entry;

            // The end entry stored at the end of this Entry::Group should
            // point to the Entry which follows the Group in the list.
            let inner = Self::inner_new(group.stream(), seq_up);
            entries[idx] = Entry::Group(group, inner);
        }

        TokenBuffer { data: entries }
    }

    /// Creates a `TokenBuffer` containing all the tokens from the input
    /// `TokenStream`.
    ///
    /// *This method is available if Syn is built with both the `"parsing"` and
    /// `"proc-macro"` features.*
    #[cfg(all(
        not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
        feature = "proc-macro"
    ))]
    pub fn new(stream: pm::TokenStream) -> TokenBuffer {
        Self::new2(stream.into())
    }

    /// Creates a `TokenBuffer` containing all the tokens from the input
    /// `TokenStream`.
    pub fn new2(stream: TokenStream) -> TokenBuffer {
        Self::inner_new(stream, ptr::null())
    }

    /// Creates a cursor referencing the first token in the buffer and able to
    /// traverse until the end of the buffer.
    pub fn begin(&self) -> Cursor {
        unsafe { Cursor::create(&self.data[0], &self.data[self.data.len() - 1]) }
    }
}

/// A cheaply copyable cursor into a `TokenBuffer`.
///
/// This cursor holds a shared reference into the immutable data which is used
/// internally to represent a `TokenStream`, and can be efficiently manipulated
/// and copied around.
///
/// An empty `Cursor` can be created directly, or one may create a `TokenBuffer`
/// object and get a cursor to its first token with `begin()`.
///
/// Two cursors are equal if they have the same location in the same input
/// stream, and have the same scope.
///
/// *This type is available if Syn is built with the `"parsing"` feature.*
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Cursor<'a> {
    // The current entry which the `Cursor` is pointing at.
    ptr: *const Entry,
    // This is the only `Entry::End(..)` object which this cursor is allowed to
    // point at. All other `End` objects are skipped over in `Cursor::create`.
    scope: *const Entry,
    // Cursor is covariant in 'a. This field ensures that our pointers are still
    // valid.
    marker: PhantomData<&'a Entry>,
}

impl<'a> Cursor<'a> {
    /// Creates a cursor referencing a static empty TokenStream.
    pub fn empty() -> Self {
        // It's safe in this situation for us to put an `Entry` object in global
        // storage, despite it not actually being safe to send across threads
        // (`Ident` is a reference into a thread-local table). This is because
        // this entry never includes a `Ident` object.
        //
        // This wrapper struct allows us to break the rules and put a `Sync`
        // object in global storage.
        struct UnsafeSyncEntry(Entry);
        unsafe impl Sync for UnsafeSyncEntry {}
        static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End(0 as *const Entry));

        Cursor {
            ptr: &EMPTY_ENTRY.0,
            scope: &EMPTY_ENTRY.0,
            marker: PhantomData,
        }
    }

    /// This create method intelligently exits non-explicitly-entered
    /// `None`-delimited scopes when the cursor reaches the end of them,
    /// allowing for them to be treated transparently.
    unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self {
        // NOTE: If we're looking at a `End(..)`, we want to advance the cursor
        // past it, unless `ptr == scope`, which means that we're at the edge of
        // our cursor's scope. We should only have `ptr != scope` at the exit
        // from None-delimited groups entered with `ignore_none`.
        while let Entry::End(exit) = *ptr {
            if ptr == scope {
                break;
            }
            ptr = exit;
        }

        Cursor {
            ptr,
            scope,
            marker: PhantomData,
        }
    }

    /// Get the current entry.
    fn entry(self) -> &'a Entry {
        unsafe { &*self.ptr }
    }

    /// Bump the cursor to point at the next token after the current one. This
    /// is undefined behavior if the cursor is currently looking at an
    /// `Entry::End`.
    unsafe fn bump(self) -> Cursor<'a> {
        Cursor::create(self.ptr.offset(1), self.scope)
    }

    /// If the cursor is looking at a `None`-delimited group, move it to look at
    /// the first token inside instead. If the group is empty, this will move
    /// the cursor past the `None`-delimited group.
    ///
    /// WARNING: This mutates its argument.
    fn ignore_none(&mut self) {
        if let Entry::Group(group, buf) = self.entry() {
            if group.delimiter() == Delimiter::None {
                // NOTE: We call `Cursor::create` here to make sure that
                // situations where we should immediately exit the span after
                // entering it are handled correctly.
                unsafe {
                    *self = Cursor::create(&buf.data[0], self.scope);
                }
            }
        }
    }

    /// Checks whether the cursor is currently pointing at the end of its valid
    /// scope.
    pub fn eof(self) -> bool {
        // We're at eof if we're at the end of our scope.
        self.ptr == self.scope
    }

    /// If the cursor is pointing at a `Group` with the given delimiter, returns
    /// a cursor into that group and one pointing to the next `TokenTree`.
    pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, Span, Cursor<'a>)> {
        // If we're not trying to enter a none-delimited group, we want to
        // ignore them. We have to make sure to _not_ ignore them when we want
        // to enter them, of course. For obvious reasons.
        if delim != Delimiter::None {
            self.ignore_none();
        }

        if let Entry::Group(group, buf) = self.entry() {
            if group.delimiter() == delim {
                return Some((buf.begin(), group.span(), unsafe { self.bump() }));
            }
        }

        None
    }

    /// If the cursor is pointing at a `Ident`, returns it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn ident(mut self) -> Option<(Ident, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Ident(ident) => Some((ident.clone(), unsafe { self.bump() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at an `Punct`, returns it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn punct(mut self) -> Option<(Punct, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Punct(op) if op.as_char() != '\'' => Some((op.clone(), unsafe { self.bump() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Literal`, return it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn literal(mut self) -> Option<(Literal, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Literal(lit) => Some((lit.clone(), unsafe { self.bump() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Lifetime`, returns it along with a
    /// cursor pointing at the next `TokenTree`.
    pub fn lifetime(mut self) -> Option<(Lifetime, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Punct(op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => {
                let next = unsafe { self.bump() };
                match next.ident() {
                    Some((ident, rest)) => {
                        let lifetime = Lifetime {
                            apostrophe: op.span(),
                            ident,
                        };
                        Some((lifetime, rest))
                    }
                    None => None,
                }
            }
            _ => None,
        }
    }

    /// Copies all remaining tokens visible from this cursor into a
    /// `TokenStream`.
    pub fn token_stream(self) -> TokenStream {
        let mut tts = Vec::new();
        let mut cursor = self;
        while let Some((tt, rest)) = cursor.token_tree() {
            tts.push(tt);
            cursor = rest;
        }
        tts.into_iter().collect()
    }

    /// If the cursor is pointing at a `TokenTree`, returns it along with a
    /// cursor pointing at the next `TokenTree`.
    ///
    /// Returns `None` if the cursor has reached the end of its stream.
    ///
    /// This method does not treat `None`-delimited groups as transparent, and
    /// will return a `Group(None, ..)` if the cursor is looking at one.
    pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> {
        let tree = match self.entry() {
            Entry::Group(group, _) => group.clone().into(),
            Entry::Literal(lit) => lit.clone().into(),
            Entry::Ident(ident) => ident.clone().into(),
            Entry::Punct(op) => op.clone().into(),
            Entry::End(..) => {
                return None;
            }
        };

        Some((tree, unsafe { self.bump() }))
    }

    /// Returns the `Span` of the current token, or `Span::call_site()` if this
    /// cursor points to eof.
    pub fn span(self) -> Span {
        match self.entry() {
            Entry::Group(group, _) => group.span(),
            Entry::Literal(l) => l.span(),
            Entry::Ident(t) => t.span(),
            Entry::Punct(o) => o.span(),
            Entry::End(..) => Span::call_site(),
        }
    }
}

pub(crate) fn same_scope(a: Cursor, b: Cursor) -> bool {
    a.scope == b.scope
}

pub(crate) fn open_span_of_group(cursor: Cursor) -> Span {
    match cursor.entry() {
        Entry::Group(group, _) => group.span_open(),
        _ => cursor.span(),
    }
}

pub(crate) fn close_span_of_group(cursor: Cursor) -> Span {
    match cursor.entry() {
        Entry::Group(group, _) => group.span_close(),
        _ => cursor.span(),
    }
}
<|endoftext|>


<commit_before>pub enum StateF<'a, S, X> {
    Get(Box<FnOnce<(S,), X> + 'a>),
    Put(S, X),
}

pub fn map<'a, S, X, Y, F:'a>(m: StateF<'a, S, X>, f: F) -> StateF<'a, S, Y>
    where
        F: FnOnce(X) -> Y,
{
    match m {
        Get(g) => Get(box move |:s| f.call_once((g.call_once((s,)),))),
        Put(s, a) => Put(s, f.call_once((a,))),
    }
}

free_monad!(State, StateF, map, [ S, ])

impl<'a, S:'a, A:'a> State<'a, S, A>
    where
        S: Clone,
{
    pub fn run(mut self, mut s: S) -> A {
        loop { match self.resume() {
            Ok(a) => return a,
            Err(Get(f)) => { self = *f.call_once((s.clone(),)) },
            Err(Put(t, a)) => { s = t; self = *a },
        }}
    }

    #[inline]
    pub fn seq<B:'a>(self, m: State<'a, S, B>) -> State<'a, S, B> {
        self.bind(move |:_| m)
    }
}

#[inline]
pub fn point<'a, S, A:'a>(a: A) -> State<'a, S, A> {
    Pure(a)
}

#[inline]
pub fn get<'a, S>() -> State<'a, S, S>
{
    Roll(Get(box |:s| box Pure(s)))
}

#[inline]
pub fn put<'a, S:'a>(s: S) -> State<'a ,S, ()> {
    Roll(Put(s, box Pure(())))
}
<commit_msg>Inline 'run'<commit_after>pub enum StateF<'a, S, X> {
    Get(Box<FnOnce<(S,), X> + 'a>),
    Put(S, X),
}

pub fn map<'a, S, X, Y, F:'a>(m: StateF<'a, S, X>, f: F) -> StateF<'a, S, Y>
    where
        F: FnOnce(X) -> Y,
{
    match m {
        Get(g) => Get(box move |:s| f.call_once((g.call_once((s,)),))),
        Put(s, a) => Put(s, f.call_once((a,))),
    }
}

free_monad!(State, StateF, map, [ S, ])

impl<'a, S:'a, A:'a> State<'a, S, A>
    where
        S: Clone,
{
    #[inline]
    pub fn run(mut self, mut s: S) -> A {
        loop { match self.resume() {
            Ok(a) => return a,
            Err(Get(f)) => { self = *f.call_once((s.clone(),)) },
            Err(Put(t, a)) => { s = t; self = *a },
        }}
    }

    #[inline]
    pub fn seq<B:'a>(self, m: State<'a, S, B>) -> State<'a, S, B> {
        self.bind(move |:_| m)
    }
}

#[inline]
pub fn point<'a, S, A:'a>(a: A) -> State<'a, S, A> {
    Pure(a)
}

#[inline]
pub fn get<'a, S>() -> State<'a, S, S>
{
    Roll(Get(box |:s| box Pure(s)))
}

#[inline]
pub fn put<'a, S:'a>(s: S) -> State<'a ,S, ()> {
    Roll(Put(s, box Pure(())))
}
<|endoftext|>