├── compiler ├── ast │ ├── src │ │ ├── visit.rs │ │ ├── ast │ │ │ ├── tests.rs │ │ │ ├── comment.rs │ │ │ ├── pat.rs │ │ │ ├── common.rs │ │ │ ├── module.rs │ │ │ ├── func.rs │ │ │ ├── class.rs │ │ │ ├── lit.rs │ │ │ ├── decl.rs │ │ │ ├── ty.rs │ │ │ └── stmt.rs │ │ ├── ast.rs │ │ └── lib.rs │ └── Cargo.toml ├── parser │ ├── src │ │ ├── parser.rs │ │ ├── lib.rs │ │ ├── context.rs │ │ └── lexer │ │ │ └── cursor.rs │ └── Cargo.toml ├── common │ ├── src │ │ ├── lib.rs │ │ ├── path.rs │ │ ├── types.rs │ │ └── compiler_options.rs │ └── Cargo.toml ├── lexer │ ├── Cargo.toml │ └── src │ │ └── cursor.rs └── span │ ├── Cargo.toml │ └── src │ ├── symbol │ └── tests.rs │ ├── fatal_error.rs │ ├── lev_distance │ └── tests.rs │ ├── lev_distance.rs │ ├── analyze_source_file │ └── tests.rs │ └── span_encoding.rs ├── .gitignore ├── rust-toolchain ├── README.md ├── rustfmt.toml ├── rustc ├── rustc_data_structures │ ├── src │ │ ├── sso │ │ │ ├── mod.rs │ │ │ └── either_iter.rs │ │ ├── captures.rs │ │ ├── fx.rs │ │ ├── base_n │ │ │ └── tests.rs │ │ ├── graph │ │ │ ├── iterate │ │ │ │ └── tests.rs │ │ │ ├── vec_graph │ │ │ │ ├── tests.rs │ │ │ │ └── mod.rs │ │ │ ├── reference.rs │ │ │ ├── dominators │ │ │ │ ├── tests.rs │ │ │ │ └── mod.rs │ │ │ ├── tests.rs │ │ │ ├── mod.rs │ │ │ └── implementation │ │ │ │ └── tests.rs │ │ ├── binary_search_util │ │ │ ├── tests.rs │ │ │ └── mod.rs │ │ ├── unhash.rs │ │ ├── ptr_key.rs │ │ ├── stack.rs │ │ ├── temp_dir.rs │ │ ├── atomic_ref.rs │ │ ├── owning_ref │ │ │ └── LICENSE │ │ ├── base_n.rs │ │ ├── macros.rs │ │ ├── small_c_str │ │ │ └── tests.rs │ │ ├── snapshot_map │ │ │ ├── tests.rs │ │ │ └── mod.rs │ │ ├── jobserver.rs │ │ ├── vec_linked_list.rs │ │ ├── work_queue.rs │ │ ├── small_c_str.rs │ │ ├── stable_set.rs │ │ ├── svh.rs │ │ ├── frozen.rs │ │ ├── steal.rs │ │ ├── functor.rs │ │ ├── thin_vec.rs │ │ ├── stable_hasher │ │ │ └── tests.rs │ │ ├── stable_map.rs │ │ ├── tiny_list.rs │ │ ├── obligation_forest │ │ │ └── graphviz.rs │ │ ├── lib.rs │ │ ├── tiny_list │ │ │ └── tests.rs │ │ ├── map_in_place.rs │ │ ├── tagged_ptr │ │ │ ├── drop.rs │ │ │ └── copy.rs │ │ ├── tagged_ptr.rs │ │ └── sharded.rs │ └── Cargo.toml ├── rustc_graphviz │ └── Cargo.toml ├── rustc_arena │ ├── Cargo.toml │ └── src │ │ └── tests.rs ├── rustc_serialize │ ├── Cargo.toml │ ├── src │ │ ├── lib.rs │ │ ├── json │ │ │ └── tests.rs │ │ └── leb128.rs │ └── tests │ │ └── leb128.rs ├── rustc_index │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── vec │ │ └── tests.rs └── rustc_macros │ ├── Cargo.toml │ └── src │ ├── type_foldable.rs │ ├── lib.rs │ ├── lift.rs │ ├── symbols │ └── tests.rs │ └── hash_stable.rs ├── .editorconfig ├── Cargo.toml └── LICENSE /compiler/ast/src/visit.rs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /compiler/parser/src/parser.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | nightly-2021-03-08 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `ts-core` 2 | 3 | Copy and paste code from `TypeScript` source code. 4 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | version = "Two" 2 | tab_spaces = 2 3 | use_small_heuristics = "Max" 4 | 5 | 6 | ignore = [ 7 | "rustc/macros" 8 | ] -------------------------------------------------------------------------------- /compiler/common/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod compiler_options; 2 | pub mod types; 3 | pub mod path; 4 | 5 | pub use compiler_options::*; 6 | pub use types::*; 7 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/sso/mod.rs: -------------------------------------------------------------------------------- 1 | mod either_iter; 2 | mod map; 3 | mod set; 4 | 5 | pub use map::SsoHashMap; 6 | pub use set::SsoHashSet; 7 | -------------------------------------------------------------------------------- /rustc/rustc_graphviz/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["The Rust Project Developers"] 3 | name = "rustc_graphviz" 4 | version = "0.0.0" 5 | edition = "2018" 6 | -------------------------------------------------------------------------------- /compiler/parser/src/lib.rs: -------------------------------------------------------------------------------- 1 | use tscore_common::ScriptKind; 2 | use tscore_common::ScriptTarget; 3 | 4 | mod context; 5 | pub mod lexer; 6 | pub mod parser; 7 | 8 | pub use parser::*; 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | indent_size = 2 9 | indent_style = space 10 | -------------------------------------------------------------------------------- /rustc/rustc_arena/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["The Rust Project Developers"] 3 | name = "rustc_arena" 4 | version = "0.0.0" 5 | edition = "2018" 6 | 7 | [dependencies] 8 | smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } 9 | -------------------------------------------------------------------------------- /compiler/ast/src/ast/tests.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | // Are ASTs encodable? 4 | #[test] 5 | fn check_asts_encodable() { 6 | fn assert_encodable rustc_serialize::Encodable>>() { 7 | } 8 | assert_encodable::(); 9 | } 10 | -------------------------------------------------------------------------------- /compiler/ast/src/ast/comment.rs: -------------------------------------------------------------------------------- 1 | use tscore_span::{symbol::Ident, Span}; 2 | 3 | #[derive(Clone, Encodable, Decodable, Debug)] 4 | pub struct JSDocTag { 5 | pub name: Ident, 6 | pub span: Span, 7 | } 8 | 9 | #[derive(Clone, Encodable, Decodable, Debug)] 10 | pub struct JSDoc { 11 | pub tags: Vec, 12 | pub span: Span, 13 | } 14 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "compiler/ast", 4 | "compiler/common", 5 | "compiler/lexer", 6 | "compiler/parser", 7 | "compiler/span", 8 | "rustc/rustc_arena", 9 | "rustc/rustc_index", 10 | "rustc/rustc_data_structures", 11 | "rustc/rustc_graphviz", 12 | "rustc/rustc_macros", 13 | "rustc/rustc_serialize" 14 | ] 15 | -------------------------------------------------------------------------------- /compiler/common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tscore_common" 3 | version = "0.0.0" 4 | authors = ["The TS-Core Developers"] 5 | license = "MIT" 6 | edition = "2018" 7 | 8 | repository = "https://github.com/rust-ts/ts-core" 9 | description = """ 10 | Common stuff for parser and compiler 11 | """ 12 | 13 | [dev-dependencies] 14 | expect-test = "1.0" -------------------------------------------------------------------------------- /rustc/rustc_serialize/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["The Rust Project Developers"] 3 | name = "rustc_serialize" 4 | version = "0.0.0" 5 | edition = "2018" 6 | 7 | [dependencies] 8 | indexmap = "1" 9 | smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } 10 | 11 | [dev-dependencies] 12 | rustc_macros = { path = "../rustc_macros" } 13 | -------------------------------------------------------------------------------- /rustc/rustc_index/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["The Rust Project Developers"] 3 | name = "rustc_index" 4 | version = "0.0.0" 5 | edition = "2018" 6 | 7 | [lib] 8 | doctest = false 9 | 10 | [dependencies] 11 | arrayvec = { version = "0.5.1", default-features = false } 12 | rustc_serialize = { path = "../rustc_serialize" } 13 | rustc_macros = { path = "../rustc_macros" } 14 | -------------------------------------------------------------------------------- /compiler/ast/src/ast/pat.rs: -------------------------------------------------------------------------------- 1 | use super::{ArrayLit, ObjectLit}; 2 | use crate::ptr::P; 3 | use tscore_span::symbol::Ident; 4 | 5 | #[derive(Clone, Encodable, Decodable, Debug)] 6 | pub enum PatKind { 7 | Ident(Ident), 8 | Array(P), 9 | Object(P), 10 | } 11 | 12 | #[derive(Clone, Encodable, Decodable, Debug)] 13 | pub struct Pat { 14 | kind: PatKind, 15 | } 16 | -------------------------------------------------------------------------------- /compiler/lexer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tscore_lexer" 3 | version = "0.0.0" 4 | authors = ["The TS-Core Developers"] 5 | edition = "2018" 6 | 7 | description = """ 8 | TypeScript lexer used by tscore. Grabbed from rustc-lexer. 9 | """ 10 | 11 | [dependencies] 12 | unicode-xid = "0.2.0" 13 | tscore_common = { path = "../common" } 14 | 15 | [dev-dependencies] 16 | expect-test = "1.0" -------------------------------------------------------------------------------- /rustc/rustc_macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rustc_macros" 3 | version = "0.0.0" 4 | authors = ["The Rust Project Developers"] 5 | edition = "2018" 6 | 7 | [lib] 8 | proc-macro = true 9 | 10 | [dependencies] 11 | synstructure = "0.12.1" 12 | syn = { version = "1", features = ["full"] } 13 | proc-macro2 = "1" 14 | quote = "1" 15 | 16 | [unstable] 17 | proc_macro_diagnostic = "yes" -------------------------------------------------------------------------------- /rustc/rustc_index/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(allow_internal_unstable)] 2 | #![feature(const_fn)] 3 | #![feature(const_panic)] 4 | #![feature(extend_one)] 5 | #![feature(unboxed_closures)] 6 | #![feature(test)] 7 | #![feature(fn_traits)] 8 | 9 | pub mod bit_set; 10 | pub mod vec; 11 | 12 | // FIXME(#56935): Work around ICEs during cross-compilation. 13 | #[allow(unused)] 14 | extern crate rustc_macros; 15 | -------------------------------------------------------------------------------- /compiler/ast/src/ast/common.rs: -------------------------------------------------------------------------------- 1 | use tscore_span::symbol::Ident; 2 | use tscore_span::Span; 3 | 4 | #[derive(Clone, Encodable, Decodable, Debug)] 5 | pub struct NameBinding { 6 | name: Ident, 7 | /// with preceding `as` keyword 8 | alias: Option, 9 | span: Span, 10 | } 11 | 12 | #[derive(Clone, Encodable, Decodable, Debug)] 13 | pub struct Spanned { 14 | pub node: T, 15 | pub span: Span, 16 | } 17 | -------------------------------------------------------------------------------- /compiler/ast/src/ast.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests; 3 | 4 | pub mod class; 5 | pub mod comment; 6 | pub mod common; 7 | pub mod decl; 8 | pub mod expr; 9 | pub mod func; 10 | pub mod lit; 11 | pub mod module; 12 | pub mod pat; 13 | pub mod stmt; 14 | pub mod ty; 15 | 16 | pub use class::*; 17 | pub use comment::*; 18 | pub use common::*; 19 | pub use decl::*; 20 | pub use expr::*; 21 | pub use func::*; 22 | pub use lit::*; 23 | pub use module::*; 24 | pub use pat::*; 25 | pub use stmt::*; 26 | pub use ty::*; 27 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/captures.rs: -------------------------------------------------------------------------------- 1 | /// "Signaling" trait used in impl trait to tag lifetimes that you may 2 | /// need to capture but don't really need for other reasons. 3 | /// Basically a workaround; see [this comment] for details. 4 | /// 5 | /// [this comment]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999 6 | // FIXME(eddyb) false positive, the lifetime parameter is "phantom" but needed. 7 | #[allow(unused_lifetimes)] 8 | pub trait Captures<'a> {} 9 | 10 | impl<'a, T: ?Sized> Captures<'a> for T {} 11 | -------------------------------------------------------------------------------- /compiler/parser/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tscore_parser" 3 | version = "0.1.0" 4 | authors = ["The TS-Core Developers"] 5 | license = "MIT" 6 | edition = "2018" 7 | 8 | repository = "https://github.com/rust-ts/ts-core" 9 | description = """ 10 | TypeScript General Parser. 11 | """ 12 | 13 | [dependencies] 14 | tscore_ast = { version = "0.1.0", path = "../ast" } 15 | tscore_common = { path = "../common" } 16 | tscore_lexer = { path = "../lexer" } 17 | tscore_span = { path = "../span" } 18 | tracing = "0.1" 19 | 20 | [dev-dependencies] 21 | expect-test = "1.0" -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/fx.rs: -------------------------------------------------------------------------------- 1 | use std::hash::BuildHasherDefault; 2 | 3 | pub use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; 4 | 5 | pub type FxIndexMap = indexmap::IndexMap>; 6 | pub type FxIndexSet = indexmap::IndexSet>; 7 | 8 | #[macro_export] 9 | macro_rules! define_id_collections { 10 | ($map_name:ident, $set_name:ident, $key:ty) => { 11 | pub type $map_name = $crate::fx::FxHashMap<$key, T>; 12 | pub type $set_name = $crate::fx::FxHashSet<$key>; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/base_n/tests.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[test] 4 | fn test_encode() { 5 | fn test(n: u128, base: usize) { 6 | assert_eq!(Ok(n), u128::from_str_radix(&encode(n, base), base as u32)); 7 | } 8 | 9 | for base in 2..37 { 10 | test(0, base); 11 | test(1, base); 12 | test(35, base); 13 | test(36, base); 14 | test(37, base); 15 | test(u64::MAX as u128, base); 16 | test(u128::MAX, base); 17 | 18 | for i in 0..1_000 { 19 | test(i * 983, base); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /compiler/ast/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tscore_ast" 3 | version = "0.1.0" 4 | authors = ["The TS-Core Developers"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | tscore_common = { path = "../common" } 9 | tscore_lexer = { path = "../lexer" } 10 | tscore_span = { path = "../span" } 11 | rustc_serialize = { path = "../../rustc/rustc_serialize" } 12 | rustc_macros = { path = "../../rustc/rustc_macros" } 13 | rustc_data_structures = { path = "../../rustc/rustc_data_structures" } 14 | rustc_index = { path = "../../rustc/rustc_index" } 15 | smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } 16 | bitflags = "1.2.1" 17 | tracing = "0.1" -------------------------------------------------------------------------------- /compiler/span/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tscore_span" 3 | version = "0.0.0" 4 | authors = ["The TS-Core Developers"] 5 | edition = "2018" 6 | 7 | [lib] 8 | doctest = false 9 | 10 | [dependencies] 11 | rustc_serialize = { path = "../../rustc/rustc_serialize" } 12 | rustc_macros = { path = "../../rustc/rustc_macros" } 13 | rustc_data_structures = { path = "../../rustc/rustc_data_structures" } 14 | rustc_index = { path = "../../rustc/rustc_index" } 15 | rustc_arena = { path = "../../rustc/rustc_arena" } 16 | scoped-tls = "1.0" 17 | unicode-width = "0.1.4" 18 | cfg-if = "0.1.2" 19 | tracing = "0.1" 20 | sha-1 = "0.9" 21 | sha2 = "0.9" 22 | md-5 = "0.9" 23 | -------------------------------------------------------------------------------- /compiler/ast/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(box_syntax)] 2 | #![feature(box_patterns)] 3 | #![feature(const_fn)] // For the `transmute` in `P::new` 4 | #![feature(const_fn_transmute)] 5 | #![feature(const_panic)] 6 | #![feature(crate_visibility_modifier)] 7 | #![feature(label_break_value)] 8 | #![feature(nll)] 9 | #![feature(or_patterns)] 10 | #![recursion_limit = "256"] 11 | 12 | #[macro_use] 13 | extern crate rustc_macros; 14 | 15 | pub mod ast; 16 | pub mod ptr; 17 | pub mod token; 18 | pub mod tokenstream; 19 | pub mod visit; 20 | 21 | pub use ast::*; 22 | 23 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; 24 | 25 | pub use tscore_span::HashStableContext; 26 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/graph/iterate/tests.rs: -------------------------------------------------------------------------------- 1 | use super::super::tests::TestGraph; 2 | 3 | use super::*; 4 | 5 | #[test] 6 | fn diamond_post_order() { 7 | let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3)]); 8 | 9 | let result = post_order_from(&graph, 0); 10 | assert_eq!(result, vec![3, 1, 2, 0]); 11 | } 12 | 13 | #[test] 14 | fn is_cyclic() { 15 | use super::super::is_cyclic; 16 | 17 | let diamond_acyclic = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3)]); 18 | let diamond_cyclic = TestGraph::new(0, &[(0, 1), (1, 2), (2, 3), (3, 0)]); 19 | 20 | assert!(!is_cyclic(&diamond_acyclic)); 21 | assert!(is_cyclic(&diamond_cyclic)); 22 | } 23 | -------------------------------------------------------------------------------- /compiler/span/src/symbol/tests.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | use crate::SessionGlobals; 4 | 5 | #[test] 6 | fn interner_tests() { 7 | let mut i: Interner = Interner::default(); 8 | // first one is zero: 9 | assert_eq!(i.intern("dog"), Symbol::new(0)); 10 | // re-use gets the same entry: 11 | assert_eq!(i.intern("dog"), Symbol::new(0)); 12 | // different string gets a different #: 13 | assert_eq!(i.intern("cat"), Symbol::new(1)); 14 | assert_eq!(i.intern("cat"), Symbol::new(1)); 15 | // dog is still at zero 16 | assert_eq!(i.intern("dog"), Symbol::new(0)); 17 | } 18 | 19 | #[test] 20 | fn without_first_quote_test() { 21 | SESSION_GLOBALS.set(&SessionGlobals::new(), || { 22 | let i = Ident::from_str("'break"); 23 | assert_eq!(i.without_first_quote().name, kw::Break); 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/binary_search_util/tests.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | type Element = (usize, &'static str); 4 | 5 | fn test_map() -> Vec { 6 | let mut data = vec![(3, "three-a"), (0, "zero"), (3, "three-b"), (22, "twenty-two")]; 7 | data.sort_by_key(get_key); 8 | data 9 | } 10 | 11 | fn get_key(data: &Element) -> usize { 12 | data.0 13 | } 14 | 15 | #[test] 16 | fn binary_search_slice_test() { 17 | let map = test_map(); 18 | assert_eq!(binary_search_slice(&map, get_key, &0), &[(0, "zero")]); 19 | assert_eq!(binary_search_slice(&map, get_key, &1), &[]); 20 | assert_eq!(binary_search_slice(&map, get_key, &3), &[(3, "three-a"), (3, "three-b")]); 21 | assert_eq!(binary_search_slice(&map, get_key, &22), &[(22, "twenty-two")]); 22 | assert_eq!(binary_search_slice(&map, get_key, &23), &[]); 23 | } 24 | -------------------------------------------------------------------------------- /compiler/ast/src/ast/module.rs: -------------------------------------------------------------------------------- 1 | use crate::ptr::P; 2 | use crate::token::{self, CommentKind, DelimToken, Token}; 3 | use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream, TokenTree}; 4 | 5 | use super::Stmt; 6 | 7 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; 8 | use rustc_data_structures::stack::ensure_sufficient_stack; 9 | use rustc_data_structures::sync::Lrc; 10 | use rustc_data_structures::thin_vec::ThinVec; 11 | use rustc_macros::HashStable_Generic; 12 | use rustc_serialize::{self, Decoder, Encoder}; 13 | use tscore_span::source_map::{respan, Spanned}; 14 | use tscore_span::symbol::{kw, sym, Ident, Symbol}; 15 | use tscore_span::{Span, DUMMY_SP}; 16 | 17 | use std::cmp::Ordering; 18 | use std::convert::TryFrom; 19 | use std::fmt; 20 | 21 | #[derive(Clone, Encodable, Decodable, Debug)] 22 | pub struct Module { 23 | pub items: Vec, 24 | } 25 | -------------------------------------------------------------------------------- /compiler/span/src/fatal_error.rs: -------------------------------------------------------------------------------- 1 | /// Used as a return value to signify a fatal error occurred. (It is also 2 | /// used as the argument to panic at the moment, but that will eventually 3 | /// not be true.) 4 | #[derive(Copy, Clone, Debug)] 5 | #[must_use] 6 | pub struct FatalError; 7 | 8 | pub struct FatalErrorMarker; 9 | 10 | // Don't implement Send on FatalError. This makes it impossible to panic!(FatalError). 11 | // We don't want to invoke the panic handler and print a backtrace for fatal errors. 12 | impl !Send for FatalError {} 13 | 14 | impl FatalError { 15 | pub fn raise(self) -> ! { 16 | std::panic::resume_unwind(Box::new(FatalErrorMarker)) 17 | } 18 | } 19 | 20 | impl std::fmt::Display for FatalError { 21 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 22 | write!(f, "parser fatal error") 23 | } 24 | } 25 | 26 | impl std::error::Error for FatalError {} 27 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/unhash.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashMap, HashSet}; 2 | use std::hash::{BuildHasherDefault, Hasher}; 3 | 4 | pub type UnhashMap = HashMap>; 5 | pub type UnhashSet = HashSet>; 6 | 7 | /// This no-op hasher expects only a single `write_u64` call. It's intended for 8 | /// map keys that already have hash-like quality, like `Fingerprint`. 9 | #[derive(Default)] 10 | pub struct Unhasher { 11 | value: u64, 12 | } 13 | 14 | impl Hasher for Unhasher { 15 | #[inline] 16 | fn finish(&self) -> u64 { 17 | self.value 18 | } 19 | 20 | fn write(&mut self, _bytes: &[u8]) { 21 | unimplemented!("use write_u64"); 22 | } 23 | 24 | #[inline] 25 | fn write_u64(&mut self, value: u64) { 26 | debug_assert_eq!(0, self.value, "Unhasher doesn't mix values!"); 27 | self.value = value; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /rustc/rustc_serialize/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Support code for encoding and decoding types. 2 | 3 | /* 4 | Core encoding and decoding interfaces. 5 | */ 6 | 7 | #![doc( 8 | html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", 9 | html_playground_url = "https://play.rust-lang.org/", 10 | test(attr(allow(unused_variables), deny(warnings))) 11 | )] 12 | #![feature(box_syntax)] 13 | #![feature(never_type)] 14 | #![feature(nll)] 15 | #![feature(associated_type_bounds)] 16 | #![feature(min_specialization)] 17 | #![feature(vec_spare_capacity)] 18 | #![feature(core_intrinsics)] 19 | #![feature(int_bits_const)] 20 | #![feature(maybe_uninit_slice)] 21 | #![feature(new_uninit)] 22 | #![cfg_attr(test, feature(test))] 23 | #![allow(rustc::internal)] 24 | 25 | pub use self::serialize::{Decodable, Decoder, Encodable, Encoder}; 26 | 27 | mod collection_impls; 28 | mod serialize; 29 | 30 | pub mod json; 31 | 32 | pub mod leb128; 33 | pub mod opaque; 34 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/ptr_key.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Deref; 2 | use std::{hash, ptr}; 3 | 4 | /// A wrapper around reference that compares and hashes like a pointer. 5 | /// Can be used as a key in sets/maps indexed by pointers to avoid `unsafe`. 6 | #[derive(Debug)] 7 | pub struct PtrKey<'a, T>(pub &'a T); 8 | 9 | impl<'a, T> Clone for PtrKey<'a, T> { 10 | fn clone(&self) -> Self { 11 | *self 12 | } 13 | } 14 | 15 | impl<'a, T> Copy for PtrKey<'a, T> {} 16 | 17 | impl<'a, T> PartialEq for PtrKey<'a, T> { 18 | fn eq(&self, rhs: &Self) -> bool { 19 | ptr::eq(self.0, rhs.0) 20 | } 21 | } 22 | 23 | impl<'a, T> Eq for PtrKey<'a, T> {} 24 | 25 | impl<'a, T> hash::Hash for PtrKey<'a, T> { 26 | fn hash(&self, hasher: &mut H) { 27 | (self.0 as *const T).hash(hasher) 28 | } 29 | } 30 | 31 | impl<'a, T> Deref for PtrKey<'a, T> { 32 | type Target = T; 33 | 34 | fn deref(&self) -> &Self::Target { 35 | self.0 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/stack.rs: -------------------------------------------------------------------------------- 1 | // This is the amount of bytes that need to be left on the stack before increasing the size. 2 | // It must be at least as large as the stack required by any code that does not call 3 | // `ensure_sufficient_stack`. 4 | const RED_ZONE: usize = 100 * 1024; // 100k 5 | 6 | // Only the first stack that is pushed, grows exponentially (2^n * STACK_PER_RECURSION) from then 7 | // on. This flag has performance relevant characteristics. Don't set it too high. 8 | const STACK_PER_RECURSION: usize = 1 * 1024 * 1024; // 1MB 9 | 10 | /// Grows the stack on demand to prevent stack overflow. Call this in strategic locations 11 | /// to "break up" recursive calls. E.g. almost any call to `visit_expr` or equivalent can benefit 12 | /// from this. 13 | /// 14 | /// Should not be sprinkled around carelessly, as it causes a little bit of overhead. 15 | pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R { 16 | stacker::maybe_grow(RED_ZONE, STACK_PER_RECURSION, f) 17 | } 18 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/temp_dir.rs: -------------------------------------------------------------------------------- 1 | use std::mem::ManuallyDrop; 2 | use std::path::Path; 3 | use tempfile::TempDir; 4 | 5 | /// This is used to avoid TempDir being dropped on error paths unintentionally. 6 | #[derive(Debug)] 7 | pub struct MaybeTempDir { 8 | dir: ManuallyDrop, 9 | // Whether the TempDir should be deleted on drop. 10 | keep: bool, 11 | } 12 | 13 | impl Drop for MaybeTempDir { 14 | fn drop(&mut self) { 15 | // SAFETY: We are in the destructor, and no further access will 16 | // occur. 17 | let dir = unsafe { ManuallyDrop::take(&mut self.dir) }; 18 | if self.keep { 19 | dir.into_path(); 20 | } 21 | } 22 | } 23 | 24 | impl AsRef for MaybeTempDir { 25 | fn as_ref(&self) -> &Path { 26 | self.dir.path() 27 | } 28 | } 29 | 30 | impl MaybeTempDir { 31 | pub fn new(dir: TempDir, keep_on_drop: bool) -> MaybeTempDir { 32 | MaybeTempDir { dir: ManuallyDrop::new(dir), keep: keep_on_drop } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/atomic_ref.rs: -------------------------------------------------------------------------------- 1 | use std::marker::PhantomData; 2 | use std::sync::atomic::{AtomicPtr, Ordering}; 3 | 4 | /// This is essentially an `AtomicPtr` but is guaranteed to always be valid 5 | pub struct AtomicRef(AtomicPtr, PhantomData<&'static T>); 6 | 7 | impl AtomicRef { 8 | pub const fn new(initial: &'static T) -> AtomicRef { 9 | AtomicRef(AtomicPtr::new(initial as *const T as *mut T), PhantomData) 10 | } 11 | 12 | pub fn swap(&self, new: &'static T) -> &'static T { 13 | // We never allow storing anything but a `'static` reference so it's safe to 14 | // return it for the same. 15 | unsafe { &*self.0.swap(new as *const T as *mut T, Ordering::SeqCst) } 16 | } 17 | } 18 | 19 | impl std::ops::Deref for AtomicRef { 20 | type Target = T; 21 | fn deref(&self) -> &Self::Target { 22 | // We never allow storing anything but a `'static` reference so it's safe to lend 23 | // it out for any amount of time. 24 | unsafe { &*self.0.load(Ordering::SeqCst) } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 rust-ts 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/graph/vec_graph/tests.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | fn create_graph() -> VecGraph { 4 | // Create a simple graph 5 | // 6 | // 5 7 | // | 8 | // V 9 | // 0 --> 1 --> 2 10 | // | 11 | // v 12 | // 3 --> 4 13 | // 14 | // 6 15 | 16 | VecGraph::new(7, vec![(0, 1), (1, 2), (1, 3), (3, 4), (5, 1)]) 17 | } 18 | 19 | #[test] 20 | fn num_nodes() { 21 | let graph = create_graph(); 22 | assert_eq!(graph.num_nodes(), 7); 23 | } 24 | 25 | #[test] 26 | fn successors() { 27 | let graph = create_graph(); 28 | assert_eq!(graph.successors(0), &[1]); 29 | assert_eq!(graph.successors(1), &[2, 3]); 30 | assert_eq!(graph.successors(2), &[]); 31 | assert_eq!(graph.successors(3), &[4]); 32 | assert_eq!(graph.successors(4), &[]); 33 | assert_eq!(graph.successors(5), &[1]); 34 | assert_eq!(graph.successors(6), &[]); 35 | } 36 | 37 | #[test] 38 | fn dfs() { 39 | let graph = create_graph(); 40 | let dfs: Vec<_> = graph.depth_first_search(0).collect(); 41 | assert_eq!(dfs, vec![0, 1, 3, 4, 2]); 42 | } 43 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/owning_ref/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Marvin Löbel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/base_n.rs: -------------------------------------------------------------------------------- 1 | /// Converts unsigned integers into a string representation with some base. 2 | /// Bases up to and including 36 can be used for case-insensitive things. 3 | use std::str; 4 | 5 | #[cfg(test)] 6 | mod tests; 7 | 8 | pub const MAX_BASE: usize = 64; 9 | pub const ALPHANUMERIC_ONLY: usize = 62; 10 | pub const CASE_INSENSITIVE: usize = 36; 11 | 12 | const BASE_64: &[u8; MAX_BASE as usize] = 13 | b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$"; 14 | 15 | #[inline] 16 | pub fn push_str(mut n: u128, base: usize, output: &mut String) { 17 | debug_assert!(base >= 2 && base <= MAX_BASE); 18 | let mut s = [0u8; 128]; 19 | let mut index = 0; 20 | 21 | let base = base as u128; 22 | 23 | loop { 24 | s[index] = BASE_64[(n % base) as usize]; 25 | index += 1; 26 | n /= base; 27 | 28 | if n == 0 { 29 | break; 30 | } 31 | } 32 | s[0..index].reverse(); 33 | 34 | output.push_str(str::from_utf8(&s[0..index]).unwrap()); 35 | } 36 | 37 | #[inline] 38 | pub fn encode(n: u128, base: usize) -> String { 39 | let mut s = String::new(); 40 | push_str(n, base, &mut s); 41 | s 42 | } 43 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/graph/reference.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | impl<'graph, G: DirectedGraph> DirectedGraph for &'graph G { 4 | type Node = G::Node; 5 | } 6 | 7 | impl<'graph, G: WithNumNodes> WithNumNodes for &'graph G { 8 | fn num_nodes(&self) -> usize { 9 | (**self).num_nodes() 10 | } 11 | } 12 | 13 | impl<'graph, G: WithStartNode> WithStartNode for &'graph G { 14 | fn start_node(&self) -> Self::Node { 15 | (**self).start_node() 16 | } 17 | } 18 | 19 | impl<'graph, G: WithSuccessors> WithSuccessors for &'graph G { 20 | fn successors(&self, node: Self::Node) -> >::Iter { 21 | (**self).successors(node) 22 | } 23 | } 24 | 25 | impl<'graph, G: WithPredecessors> WithPredecessors for &'graph G { 26 | fn predecessors(&self, node: Self::Node) -> >::Iter { 27 | (**self).predecessors(node) 28 | } 29 | } 30 | 31 | impl<'iter, 'graph, G: WithPredecessors> GraphPredecessors<'iter> for &'graph G { 32 | type Item = G::Node; 33 | type Iter = >::Iter; 34 | } 35 | 36 | impl<'iter, 'graph, G: WithSuccessors> GraphSuccessors<'iter> for &'graph G { 37 | type Item = G::Node; 38 | type Iter = >::Iter; 39 | } 40 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["The Rust Project Developers"] 3 | name = "rustc_data_structures" 4 | version = "0.0.0" 5 | edition = "2018" 6 | 7 | [lib] 8 | doctest = false 9 | 10 | [dependencies] 11 | arrayvec = { version = "0.5.1", default-features = false } 12 | ena = "0.14" 13 | indexmap = "1.5.1" 14 | tracing = "0.1" 15 | jobserver_crate = { version = "0.1.13", package = "jobserver" } 16 | rustc_serialize = { path = "../rustc_serialize" } 17 | rustc_macros = { path = "../rustc_macros" } 18 | rustc_graphviz = { path = "../rustc_graphviz" } 19 | cfg-if = "0.1.2" 20 | crossbeam-utils = { version = "0.7", features = ["nightly"] } 21 | stable_deref_trait = "1.0.0" 22 | rayon = { version = "0.3.0", package = "rustc-rayon" } 23 | rayon-core = { version = "0.3.0", package = "rustc-rayon-core" } 24 | rustc-hash = "1.1.0" 25 | smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } 26 | rustc_index = { path = "../rustc_index", package = "rustc_index" } 27 | bitflags = "1.2.1" 28 | measureme = "9.1.0" 29 | libc = "0.2" 30 | stacker = "0.1.12" 31 | tempfile = "3.0.5" 32 | 33 | [dependencies.parking_lot] 34 | version = "0.11" 35 | features = ["nightly"] 36 | 37 | [target.'cfg(windows)'.dependencies] 38 | winapi = { version = "0.3", features = ["fileapi", "psapi"] } 39 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/graph/dominators/tests.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | use super::super::tests::TestGraph; 4 | 5 | #[test] 6 | fn diamond() { 7 | let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3)]); 8 | 9 | let dominators = dominators(&graph); 10 | let immediate_dominators = &dominators.immediate_dominators; 11 | assert_eq!(immediate_dominators[0], Some(0)); 12 | assert_eq!(immediate_dominators[1], Some(0)); 13 | assert_eq!(immediate_dominators[2], Some(0)); 14 | assert_eq!(immediate_dominators[3], Some(0)); 15 | } 16 | 17 | #[test] 18 | fn paper() { 19 | // example from the paper: 20 | let graph = TestGraph::new( 21 | 6, 22 | &[(6, 5), (6, 4), (5, 1), (4, 2), (4, 3), (1, 2), (2, 3), (3, 2), (2, 1)], 23 | ); 24 | 25 | let dominators = dominators(&graph); 26 | let immediate_dominators = &dominators.immediate_dominators; 27 | assert_eq!(immediate_dominators[0], None); // <-- note that 0 is not in graph 28 | assert_eq!(immediate_dominators[1], Some(6)); 29 | assert_eq!(immediate_dominators[2], Some(6)); 30 | assert_eq!(immediate_dominators[3], Some(6)); 31 | assert_eq!(immediate_dominators[4], Some(6)); 32 | assert_eq!(immediate_dominators[5], Some(6)); 33 | assert_eq!(immediate_dominators[6], Some(6)); 34 | } 35 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/macros.rs: -------------------------------------------------------------------------------- 1 | /// Type size assertion. The first argument is a type and the second argument is its expected size. 2 | #[macro_export] 3 | macro_rules! static_assert_size { 4 | ($ty:ty, $size:expr) => { 5 | const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()]; 6 | }; 7 | } 8 | 9 | #[macro_export] 10 | macro_rules! enum_from_u32 { 11 | ($(#[$attr:meta])* pub enum $name:ident { 12 | $($variant:ident = $e:expr,)* 13 | }) => { 14 | $(#[$attr])* 15 | pub enum $name { 16 | $($variant = $e),* 17 | } 18 | 19 | impl $name { 20 | pub fn from_u32(u: u32) -> Option<$name> { 21 | $(if u == $name::$variant as u32 { 22 | return Some($name::$variant) 23 | })* 24 | None 25 | } 26 | } 27 | }; 28 | ($(#[$attr:meta])* pub enum $name:ident { 29 | $($variant:ident,)* 30 | }) => { 31 | $(#[$attr])* 32 | pub enum $name { 33 | $($variant,)* 34 | } 35 | 36 | impl $name { 37 | pub fn from_u32(u: u32) -> Option<$name> { 38 | $(if u == $name::$variant as u32 { 39 | return Some($name::$variant) 40 | })* 41 | None 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/small_c_str/tests.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[test] 4 | fn short() { 5 | const TEXT: &str = "abcd"; 6 | let reference = ffi::CString::new(TEXT.to_string()).unwrap(); 7 | 8 | let scs = SmallCStr::new(TEXT); 9 | 10 | assert_eq!(scs.len_with_nul(), TEXT.len() + 1); 11 | assert_eq!(scs.as_c_str(), reference.as_c_str()); 12 | assert!(!scs.spilled()); 13 | } 14 | 15 | #[test] 16 | fn empty() { 17 | const TEXT: &str = ""; 18 | let reference = ffi::CString::new(TEXT.to_string()).unwrap(); 19 | 20 | let scs = SmallCStr::new(TEXT); 21 | 22 | assert_eq!(scs.len_with_nul(), TEXT.len() + 1); 23 | assert_eq!(scs.as_c_str(), reference.as_c_str()); 24 | assert!(!scs.spilled()); 25 | } 26 | 27 | #[test] 28 | fn long() { 29 | const TEXT: &str = "01234567890123456789012345678901234567890123456789\ 30 | 01234567890123456789012345678901234567890123456789\ 31 | 01234567890123456789012345678901234567890123456789"; 32 | let reference = ffi::CString::new(TEXT.to_string()).unwrap(); 33 | 34 | let scs = SmallCStr::new(TEXT); 35 | 36 | assert_eq!(scs.len_with_nul(), TEXT.len() + 1); 37 | assert_eq!(scs.as_c_str(), reference.as_c_str()); 38 | assert!(scs.spilled()); 39 | } 40 | 41 | #[test] 42 | #[should_panic] 43 | fn internal_nul() { 44 | let _ = SmallCStr::new("abcd\0def"); 45 | } 46 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/snapshot_map/tests.rs: -------------------------------------------------------------------------------- 1 | use super::SnapshotMap; 2 | 3 | #[test] 4 | fn basic() { 5 | let mut map = SnapshotMap::default(); 6 | map.insert(22, "twenty-two"); 7 | let snapshot = map.snapshot(); 8 | map.insert(22, "thirty-three"); 9 | assert_eq!(map[&22], "thirty-three"); 10 | map.insert(44, "forty-four"); 11 | assert_eq!(map[&44], "forty-four"); 12 | assert_eq!(map.get(&33), None); 13 | map.rollback_to(snapshot); 14 | assert_eq!(map[&22], "twenty-two"); 15 | assert_eq!(map.get(&33), None); 16 | assert_eq!(map.get(&44), None); 17 | } 18 | 19 | #[test] 20 | #[should_panic] 21 | fn out_of_order() { 22 | let mut map = SnapshotMap::default(); 23 | map.insert(22, "twenty-two"); 24 | let snapshot1 = map.snapshot(); 25 | map.insert(33, "thirty-three"); 26 | let snapshot2 = map.snapshot(); 27 | map.insert(44, "forty-four"); 28 | map.rollback_to(snapshot1); // bogus, but accepted 29 | map.rollback_to(snapshot2); // asserts 30 | } 31 | 32 | #[test] 33 | fn nested_commit_then_rollback() { 34 | let mut map = SnapshotMap::default(); 35 | map.insert(22, "twenty-two"); 36 | let snapshot1 = map.snapshot(); 37 | let snapshot2 = map.snapshot(); 38 | map.insert(22, "thirty-three"); 39 | map.commit(snapshot2); 40 | assert_eq!(map[&22], "thirty-three"); 41 | map.rollback_to(snapshot1); 42 | assert_eq!(map[&22], "twenty-two"); 43 | } 44 | -------------------------------------------------------------------------------- /compiler/common/src/path.rs: -------------------------------------------------------------------------------- 1 | use std::path::{Component, Path, PathBuf}; 2 | 3 | pub fn normalize_path(path: String) -> String { 4 | let mut buf = PathBuf::new(); 5 | for component in Path::new(&path).components() { 6 | match component { 7 | Component::RootDir => { 8 | buf.clear(); 9 | buf.push(component); 10 | } 11 | Component::ParentDir => { 12 | buf.pop(); 13 | } 14 | Component::Normal(s) => { 15 | buf.push(s); 16 | } 17 | _ => (), 18 | } 19 | } 20 | 21 | match buf.to_str() { 22 | Some(s) => s.to_string(), 23 | None => path, 24 | } 25 | } 26 | 27 | #[inline] 28 | pub fn is_declaration_file(file_name: &str) -> bool { 29 | file_name.ends_with(".d.ts") 30 | } 31 | 32 | #[cfg(test)] 33 | mod tests { 34 | use super::*; 35 | use expect_test::{expect, Expect}; 36 | 37 | fn expect_equal(paths: &str, expect: Expect) { 38 | let actual: String = paths 39 | .split('\n') 40 | .filter_map( 41 | |path| if path.is_empty() { None } else { Some(normalize_path(path.to_string())) }, 42 | ) 43 | .collect::>() 44 | .join("\n"); 45 | expect.assert_eq(&actual) 46 | } 47 | 48 | #[test] 49 | fn test_normalize_path() { 50 | expect_equal( 51 | r" 52 | /tmp/foo.txt 53 | C:\tmp\foo.txt 54 | /tmp/../foo/./bar.txt 55 | /tmp/foo/../../bar.txt 56 | ", 57 | expect![[r#" 58 | /tmp/foo.txt 59 | C:\tmp\foo.txt 60 | /foo/bar.txt 61 | /bar.txt"#]], 62 | ) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/jobserver.rs: -------------------------------------------------------------------------------- 1 | pub use jobserver_crate::Client; 2 | use std::lazy::SyncLazy; 3 | 4 | // We can only call `from_env` once per process 5 | 6 | // Note that this is unsafe because it may misinterpret file descriptors 7 | // on Unix as jobserver file descriptors. We hopefully execute this near 8 | // the beginning of the process though to ensure we don't get false 9 | // positives, or in other words we try to execute this before we open 10 | // any file descriptors ourselves. 11 | // 12 | // Pick a "reasonable maximum" if we don't otherwise have 13 | // a jobserver in our environment, capping out at 32 so we 14 | // don't take everything down by hogging the process run queue. 15 | // The fixed number is used to have deterministic compilation 16 | // across machines. 17 | // 18 | // Also note that we stick this in a global because there could be 19 | // multiple rustc instances in this process, and the jobserver is 20 | // per-process. 21 | static GLOBAL_CLIENT: SyncLazy = SyncLazy::new(|| unsafe { 22 | Client::from_env().unwrap_or_else(|| { 23 | let client = Client::new(32).expect("failed to create jobserver"); 24 | // Acquire a token for the main thread which we can release later 25 | client.acquire_raw().ok(); 26 | client 27 | }) 28 | }); 29 | 30 | pub fn client() -> Client { 31 | GLOBAL_CLIENT.clone() 32 | } 33 | 34 | pub fn acquire_thread() { 35 | GLOBAL_CLIENT.acquire_raw().ok(); 36 | } 37 | 38 | pub fn release_thread() { 39 | GLOBAL_CLIENT.release_raw().ok(); 40 | } 41 | -------------------------------------------------------------------------------- /rustc/rustc_macros/src/type_foldable.rs: -------------------------------------------------------------------------------- 1 | use quote::quote; 2 | 3 | pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { 4 | if let syn::Data::Union(_) = s.ast().data { 5 | panic!("cannot derive on union") 6 | } 7 | 8 | s.add_bounds(synstructure::AddBounds::Generics); 9 | let body_visit = s.each(|bind| { 10 | quote! { 11 | ::rustc_middle::ty::fold::TypeFoldable::visit_with(#bind, __folder)?; 12 | } 13 | }); 14 | s.bind_with(|_| synstructure::BindStyle::Move); 15 | let body_fold = s.each_variant(|vi| { 16 | let bindings = vi.bindings(); 17 | vi.construct(|_, index| { 18 | let bind = &bindings[index]; 19 | quote! { 20 | ::rustc_middle::ty::fold::TypeFoldable::fold_with(#bind, __folder) 21 | } 22 | }) 23 | }); 24 | 25 | s.bound_impl( 26 | quote!(::rustc_middle::ty::fold::TypeFoldable<'tcx>), 27 | quote! { 28 | fn super_fold_with<__F: ::rustc_middle::ty::fold::TypeFolder<'tcx>>( 29 | self, 30 | __folder: &mut __F 31 | ) -> Self { 32 | match self { #body_fold } 33 | } 34 | 35 | fn super_visit_with<__F: ::rustc_middle::ty::fold::TypeVisitor<'tcx>>( 36 | &self, 37 | __folder: &mut __F 38 | ) -> ::std::ops::ControlFlow<__F::BreakTy> { 39 | match *self { #body_visit } 40 | ::std::ops::ControlFlow::CONTINUE 41 | } 42 | }, 43 | ) 44 | } 45 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/vec_linked_list.rs: -------------------------------------------------------------------------------- 1 | use rustc_index::vec::{Idx, IndexVec}; 2 | 3 | pub fn iter( 4 | first: Option, 5 | links: &'a Ls, 6 | ) -> impl Iterator + 'a 7 | where 8 | Ls: Links, 9 | { 10 | VecLinkedListIterator { links, current: first } 11 | } 12 | 13 | pub struct VecLinkedListIterator 14 | where 15 | Ls: Links, 16 | { 17 | links: Ls, 18 | current: Option, 19 | } 20 | 21 | impl Iterator for VecLinkedListIterator 22 | where 23 | Ls: Links, 24 | { 25 | type Item = Ls::LinkIndex; 26 | 27 | fn next(&mut self) -> Option { 28 | if let Some(c) = self.current { 29 | self.current = ::next(&self.links, c); 30 | Some(c) 31 | } else { 32 | None 33 | } 34 | } 35 | } 36 | 37 | pub trait Links { 38 | type LinkIndex: Copy; 39 | 40 | fn next(links: &Self, index: Self::LinkIndex) -> Option; 41 | } 42 | 43 | impl Links for &Ls 44 | where 45 | Ls: Links, 46 | { 47 | type LinkIndex = Ls::LinkIndex; 48 | 49 | fn next(links: &Self, index: Ls::LinkIndex) -> Option { 50 | ::next(links, index) 51 | } 52 | } 53 | 54 | pub trait LinkElem { 55 | type LinkIndex: Copy; 56 | 57 | fn next(elem: &Self) -> Option; 58 | } 59 | 60 | impl Links for IndexVec 61 | where 62 | E: LinkElem, 63 | L: Idx, 64 | { 65 | type LinkIndex = L; 66 | 67 | fn next(links: &Self, index: L) -> Option { 68 | ::next(&links[index]) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /rustc/rustc_index/src/vec/tests.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | newtype_index!(struct MyIdx { MAX = 0xFFFF_FFFA }); 3 | 4 | #[test] 5 | fn index_size_is_optimized() { 6 | use std::mem::size_of; 7 | 8 | assert_eq!(size_of::(), 4); 9 | // Uses 0xFFFF_FFFB 10 | assert_eq!(size_of::>(), 4); 11 | // Uses 0xFFFF_FFFC 12 | assert_eq!(size_of::>>(), 4); 13 | // Uses 0xFFFF_FFFD 14 | assert_eq!(size_of::>>>(), 4); 15 | // Uses 0xFFFF_FFFE 16 | assert_eq!(size_of::>>>>(), 4); 17 | // Uses 0xFFFF_FFFF 18 | assert_eq!(size_of::>>>>>(), 4); 19 | // Uses a tag 20 | assert_eq!(size_of::>>>>>>(), 8); 21 | } 22 | 23 | #[test] 24 | fn range_iterator_iterates_forwards() { 25 | let range = MyIdx::from_u32(1)..MyIdx::from_u32(4); 26 | assert_eq!( 27 | range.collect::>(), 28 | [MyIdx::from_u32(1), MyIdx::from_u32(2), MyIdx::from_u32(3)] 29 | ); 30 | } 31 | 32 | #[test] 33 | fn range_iterator_iterates_backwards() { 34 | let range = MyIdx::from_u32(1)..MyIdx::from_u32(4); 35 | assert_eq!( 36 | range.rev().collect::>(), 37 | [MyIdx::from_u32(3), MyIdx::from_u32(2), MyIdx::from_u32(1)] 38 | ); 39 | } 40 | 41 | #[test] 42 | fn range_count_is_correct() { 43 | let range = MyIdx::from_u32(1)..MyIdx::from_u32(4); 44 | assert_eq!(range.count(), 3); 45 | } 46 | 47 | #[test] 48 | fn range_size_hint_is_correct() { 49 | let range = MyIdx::from_u32(1)..MyIdx::from_u32(4); 50 | assert_eq!(range.size_hint(), (3, Some(3))); 51 | } 52 | -------------------------------------------------------------------------------- /rustc/rustc_macros/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(proc_macro_diagnostic)] 2 | #![allow(rustc::default_hash_types)] 3 | #![recursion_limit = "128"] 4 | 5 | use synstructure::decl_derive; 6 | 7 | use proc_macro::TokenStream; 8 | 9 | mod hash_stable; 10 | mod lift; 11 | mod query; 12 | mod serialize; 13 | mod session_diagnostic; 14 | mod symbols; 15 | mod type_foldable; 16 | 17 | #[proc_macro] 18 | pub fn rustc_queries(input: TokenStream) -> TokenStream { 19 | query::rustc_queries(input) 20 | } 21 | 22 | #[proc_macro] 23 | pub fn symbols(input: TokenStream) -> TokenStream { 24 | symbols::symbols(input.into()).into() 25 | } 26 | 27 | decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive); 28 | decl_derive!( 29 | [HashStable_Generic, attributes(stable_hasher)] => 30 | hash_stable::hash_stable_generic_derive 31 | ); 32 | 33 | decl_derive!([Decodable] => serialize::decodable_derive); 34 | decl_derive!([Encodable] => serialize::encodable_derive); 35 | decl_derive!([TyDecodable] => serialize::type_decodable_derive); 36 | decl_derive!([TyEncodable] => serialize::type_encodable_derive); 37 | decl_derive!([MetadataDecodable] => serialize::meta_decodable_derive); 38 | decl_derive!([MetadataEncodable] => serialize::meta_encodable_derive); 39 | decl_derive!([TypeFoldable, attributes(type_foldable)] => type_foldable::type_foldable_derive); 40 | decl_derive!([Lift, attributes(lift)] => lift::lift_derive); 41 | decl_derive!( 42 | [SessionDiagnostic, attributes( 43 | message, 44 | lint, 45 | error, 46 | label, 47 | suggestion, 48 | suggestion_short, 49 | suggestion_hidden, 50 | suggestion_verbose)] => session_diagnostic::session_diagnostic_derive 51 | ); 52 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/work_queue.rs: -------------------------------------------------------------------------------- 1 | use rustc_index::bit_set::BitSet; 2 | use rustc_index::vec::Idx; 3 | use std::collections::VecDeque; 4 | 5 | /// A work queue is a handy data structure for tracking work left to 6 | /// do. (For example, basic blocks left to process.) It is basically a 7 | /// de-duplicating queue; so attempting to insert X if X is already 8 | /// enqueued has no effect. This implementation assumes that the 9 | /// elements are dense indices, so it can allocate the queue to size 10 | /// and also use a bit set to track occupancy. 11 | pub struct WorkQueue { 12 | deque: VecDeque, 13 | set: BitSet, 14 | } 15 | 16 | impl WorkQueue { 17 | /// Creates a new work queue that starts empty, where elements range from (0..len). 18 | #[inline] 19 | pub fn with_none(len: usize) -> Self { 20 | WorkQueue { deque: VecDeque::with_capacity(len), set: BitSet::new_empty(len) } 21 | } 22 | 23 | /// Attempt to enqueue `element` in the work queue. Returns false if it was already present. 24 | #[inline] 25 | pub fn insert(&mut self, element: T) -> bool { 26 | if self.set.insert(element) { 27 | self.deque.push_back(element); 28 | true 29 | } else { 30 | false 31 | } 32 | } 33 | 34 | /// Attempt to pop an element from the work queue. 35 | #[inline] 36 | pub fn pop(&mut self) -> Option { 37 | if let Some(element) = self.deque.pop_front() { 38 | self.set.remove(element); 39 | Some(element) 40 | } else { 41 | None 42 | } 43 | } 44 | 45 | /// Returns `true` if nothing is enqueued. 46 | #[inline] 47 | pub fn is_empty(&self) -> bool { 48 | self.deque.is_empty() 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /rustc/rustc_macros/src/lift.rs: -------------------------------------------------------------------------------- 1 | use quote::quote; 2 | use syn::{self, parse_quote}; 3 | 4 | pub fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { 5 | s.add_bounds(synstructure::AddBounds::Generics); 6 | s.bind_with(|_| synstructure::BindStyle::Move); 7 | 8 | let tcx: syn::Lifetime = parse_quote!('tcx); 9 | let newtcx: syn::GenericParam = parse_quote!('__lifted); 10 | 11 | let lifted = { 12 | let ast = s.ast(); 13 | let ident = &ast.ident; 14 | 15 | // Replace `'tcx` lifetime by the `'__lifted` lifetime 16 | let (_, generics, _) = ast.generics.split_for_impl(); 17 | let mut generics: syn::AngleBracketedGenericArguments = syn::parse_quote! { #generics }; 18 | for arg in generics.args.iter_mut() { 19 | match arg { 20 | syn::GenericArgument::Lifetime(l) if *l == tcx => { 21 | *arg = parse_quote!('__lifted); 22 | } 23 | syn::GenericArgument::Type(t) => { 24 | *arg = syn::parse_quote! { #t::Lifted }; 25 | } 26 | _ => {} 27 | } 28 | } 29 | 30 | quote! { #ident #generics } 31 | }; 32 | 33 | let body = s.each_variant(|vi| { 34 | let bindings = &vi.bindings(); 35 | vi.construct(|_, index| { 36 | let bi = &bindings[index]; 37 | quote! { __tcx.lift(#bi)? } 38 | }) 39 | }); 40 | 41 | s.add_impl_generic(newtcx); 42 | s.bound_impl( 43 | quote!(::rustc_middle::ty::Lift<'__lifted>), 44 | quote! { 45 | type Lifted = #lifted; 46 | 47 | fn lift_to_tcx(self, __tcx: ::rustc_middle::ty::TyCtxt<'__lifted>) -> Option<#lifted> { 48 | Some(match self { #body }) 49 | } 50 | }, 51 | ) 52 | } 53 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/small_c_str.rs: -------------------------------------------------------------------------------- 1 | use std::ffi; 2 | use std::ops::Deref; 3 | 4 | use smallvec::SmallVec; 5 | 6 | #[cfg(test)] 7 | mod tests; 8 | 9 | const SIZE: usize = 36; 10 | 11 | /// Like SmallVec but for C strings. 12 | #[derive(Clone)] 13 | pub struct SmallCStr { 14 | data: SmallVec<[u8; SIZE]>, 15 | } 16 | 17 | impl SmallCStr { 18 | #[inline] 19 | pub fn new(s: &str) -> SmallCStr { 20 | let len = s.len(); 21 | let len1 = len + 1; 22 | let data = if len < SIZE { 23 | let mut buf = [0; SIZE]; 24 | buf[..len].copy_from_slice(s.as_bytes()); 25 | SmallVec::from_buf_and_len(buf, len1) 26 | } else { 27 | let mut data = Vec::with_capacity(len1); 28 | data.extend_from_slice(s.as_bytes()); 29 | data.push(0); 30 | SmallVec::from_vec(data) 31 | }; 32 | if let Err(e) = ffi::CStr::from_bytes_with_nul(&data) { 33 | panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e); 34 | } 35 | SmallCStr { data } 36 | } 37 | 38 | #[inline] 39 | pub fn new_with_nul(s: &str) -> SmallCStr { 40 | let b = s.as_bytes(); 41 | if let Err(e) = ffi::CStr::from_bytes_with_nul(b) { 42 | panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e); 43 | } 44 | SmallCStr { data: SmallVec::from_slice(s.as_bytes()) } 45 | } 46 | 47 | #[inline] 48 | pub fn as_c_str(&self) -> &ffi::CStr { 49 | unsafe { ffi::CStr::from_bytes_with_nul_unchecked(&self.data[..]) } 50 | } 51 | 52 | #[inline] 53 | pub fn len_with_nul(&self) -> usize { 54 | self.data.len() 55 | } 56 | 57 | pub fn spilled(&self) -> bool { 58 | self.data.spilled() 59 | } 60 | } 61 | 62 | impl Deref for SmallCStr { 63 | type Target = ffi::CStr; 64 | 65 | fn deref(&self) -> &ffi::CStr { 66 | self.as_c_str() 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /compiler/ast/src/ast/func.rs: -------------------------------------------------------------------------------- 1 | use crate::ptr::P; 2 | use crate::token::{self, CommentKind, DelimToken, Token}; 3 | use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream, TokenTree}; 4 | 5 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; 6 | use rustc_data_structures::stack::ensure_sufficient_stack; 7 | use rustc_data_structures::sync::Lrc; 8 | use rustc_data_structures::thin_vec::ThinVec; 9 | use rustc_macros::HashStable_Generic; 10 | use rustc_serialize::{self, Decoder, Encoder}; 11 | use tscore_span::source_map::{respan, Spanned}; 12 | use tscore_span::symbol::{kw, sym, Ident, Symbol}; 13 | use tscore_span::{Span, DUMMY_SP}; 14 | 15 | use super::{Block, Decorator, Expr, FnSig, Generics, JSDoc, Lit, Pat, Ty}; 16 | 17 | #[derive(Clone, Encodable, Decodable, Debug)] 18 | pub struct FnParam { 19 | pub ty: P, 20 | pub name: P, 21 | pub decorators: Vec, 22 | } 23 | 24 | #[derive(Clone, Encodable, Decodable, Debug)] 25 | pub enum FnBody { 26 | Block(P), 27 | Expr(P), 28 | } 29 | 30 | #[derive(Clone, Encodable, Decodable, Debug)] 31 | pub struct Fn { 32 | /// Optional for arrow function or anonymous function. 33 | /// 34 | /// ```js 35 | /// const fnA = () => { ... } 36 | /// const fnB = function() { ... } 37 | /// const fnC = () => { ... } 38 | /// ``` 39 | pub name: Option, 40 | /// Function Signature 41 | pub sig: FnSig, 42 | /// TODO: what if a ts function declaration? 43 | pub body: P, 44 | /// Indicate whether a function is `async` function. 45 | /// 46 | /// ```js 47 | /// async function longTask() { 48 | /// // ... 49 | /// } 50 | /// ``` 51 | pub asyncness: Option, 52 | /// Indicate whether a function is `generator`. 53 | /// 54 | /// ```js 55 | /// function* generator(i) { 56 | /// yield i; 57 | /// yield i + 10; 58 | /// } 59 | /// ``` 60 | pub generator: Option, 61 | pub decorators: Vec, 62 | pub span: Span, 63 | pub js_docs: Vec, 64 | } 65 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/stable_set.rs: -------------------------------------------------------------------------------- 1 | pub use rustc_hash::FxHashSet; 2 | use std::borrow::Borrow; 3 | use std::fmt; 4 | use std::hash::Hash; 5 | 6 | /// A deterministic wrapper around FxHashSet that does not provide iteration support. 7 | /// 8 | /// It supports insert, remove, get functions from FxHashSet. 9 | /// It also allows to convert hashset to a sorted vector with the method `into_sorted_vector()`. 10 | #[derive(Clone)] 11 | pub struct StableSet { 12 | base: FxHashSet, 13 | } 14 | 15 | impl Default for StableSet 16 | where 17 | T: Eq + Hash, 18 | { 19 | fn default() -> StableSet { 20 | StableSet::new() 21 | } 22 | } 23 | 24 | impl fmt::Debug for StableSet 25 | where 26 | T: Eq + Hash + fmt::Debug, 27 | { 28 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 29 | write!(f, "{:?}", self.base) 30 | } 31 | } 32 | 33 | impl PartialEq> for StableSet 34 | where 35 | T: Eq + Hash, 36 | { 37 | fn eq(&self, other: &StableSet) -> bool { 38 | self.base == other.base 39 | } 40 | } 41 | 42 | impl Eq for StableSet where T: Eq + Hash {} 43 | 44 | impl StableSet { 45 | pub fn new() -> StableSet { 46 | StableSet { base: FxHashSet::default() } 47 | } 48 | 49 | pub fn into_sorted_vector(self) -> Vec 50 | where 51 | T: Ord, 52 | { 53 | let mut vector = self.base.into_iter().collect::>(); 54 | vector.sort_unstable(); 55 | vector 56 | } 57 | 58 | pub fn get(&self, value: &Q) -> Option<&T> 59 | where 60 | T: Borrow, 61 | Q: Hash + Eq, 62 | { 63 | self.base.get(value) 64 | } 65 | 66 | pub fn insert(&mut self, value: T) -> bool { 67 | self.base.insert(value) 68 | } 69 | 70 | pub fn remove(&mut self, value: &Q) -> bool 71 | where 72 | T: Borrow, 73 | Q: Hash + Eq, 74 | { 75 | self.base.remove(value) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/sso/either_iter.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::iter::ExactSizeIterator; 3 | use std::iter::FusedIterator; 4 | use std::iter::Iterator; 5 | 6 | /// Iterator which may contain instance of 7 | /// one of two specific implementations. 8 | /// 9 | /// Note: For most methods providing custom 10 | /// implementation may margianlly 11 | /// improve performance by avoiding 12 | /// doing Left/Right match on every step 13 | /// and doing it only once instead. 14 | #[derive(Clone)] 15 | pub enum EitherIter { 16 | Left(L), 17 | Right(R), 18 | } 19 | 20 | impl Iterator for EitherIter 21 | where 22 | L: Iterator, 23 | R: Iterator, 24 | { 25 | type Item = L::Item; 26 | 27 | fn next(&mut self) -> Option { 28 | match self { 29 | EitherIter::Left(l) => l.next(), 30 | EitherIter::Right(r) => r.next(), 31 | } 32 | } 33 | 34 | fn size_hint(&self) -> (usize, Option) { 35 | match self { 36 | EitherIter::Left(l) => l.size_hint(), 37 | EitherIter::Right(r) => r.size_hint(), 38 | } 39 | } 40 | } 41 | 42 | impl ExactSizeIterator for EitherIter 43 | where 44 | L: ExactSizeIterator, 45 | R: ExactSizeIterator, 46 | EitherIter: Iterator, 47 | { 48 | fn len(&self) -> usize { 49 | match self { 50 | EitherIter::Left(l) => l.len(), 51 | EitherIter::Right(r) => r.len(), 52 | } 53 | } 54 | } 55 | 56 | impl FusedIterator for EitherIter 57 | where 58 | L: FusedIterator, 59 | R: FusedIterator, 60 | EitherIter: Iterator, 61 | { 62 | } 63 | 64 | impl fmt::Debug for EitherIter 65 | where 66 | L: fmt::Debug, 67 | R: fmt::Debug, 68 | { 69 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 70 | match self { 71 | EitherIter::Left(l) => l.fmt(f), 72 | EitherIter::Right(r) => r.fmt(f), 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/svh.rs: -------------------------------------------------------------------------------- 1 | //! Calculation and management of a Strict Version Hash for crates 2 | //! 3 | //! The SVH is used for incremental compilation to track when HIR 4 | //! nodes have changed between compilations, and also to detect 5 | //! mismatches where we have two versions of the same crate that were 6 | //! compiled from distinct sources. 7 | 8 | use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; 9 | use std::fmt; 10 | use std::hash::{Hash, Hasher}; 11 | 12 | use crate::stable_hasher; 13 | 14 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] 15 | pub struct Svh { 16 | hash: u64, 17 | } 18 | 19 | impl Svh { 20 | /// Creates a new `Svh` given the hash. If you actually want to 21 | /// compute the SVH from some HIR, you want the `calculate_svh` 22 | /// function found in `librustc_incremental`. 23 | pub fn new(hash: u64) -> Svh { 24 | Svh { hash } 25 | } 26 | 27 | pub fn as_u64(&self) -> u64 { 28 | self.hash 29 | } 30 | 31 | pub fn to_string(&self) -> String { 32 | format!("{:016x}", self.hash) 33 | } 34 | } 35 | 36 | impl Hash for Svh { 37 | fn hash(&self, state: &mut H) 38 | where 39 | H: Hasher, 40 | { 41 | self.hash.to_le().hash(state); 42 | } 43 | } 44 | 45 | impl fmt::Display for Svh { 46 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 47 | f.pad(&self.to_string()) 48 | } 49 | } 50 | 51 | impl Encodable for Svh { 52 | fn encode(&self, s: &mut S) -> Result<(), S::Error> { 53 | s.emit_u64(self.as_u64().to_le()) 54 | } 55 | } 56 | 57 | impl Decodable for Svh { 58 | fn decode(d: &mut D) -> Result { 59 | d.read_u64().map(u64::from_le).map(Svh::new) 60 | } 61 | } 62 | 63 | impl stable_hasher::HashStable for Svh { 64 | #[inline] 65 | fn hash_stable(&self, ctx: &mut T, hasher: &mut stable_hasher::StableHasher) { 66 | let Svh { hash } = *self; 67 | hash.hash_stable(ctx, hasher); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/frozen.rs: -------------------------------------------------------------------------------- 1 | //! An immutable, owned value (except for interior mutability). 2 | //! 3 | //! The purpose of `Frozen` is to make a value immutable for the sake of defensive programming. For example, 4 | //! suppose we have the following: 5 | //! 6 | //! ```rust 7 | //! struct Bar { /* some data */ } 8 | //! 9 | //! struct Foo { 10 | //! /// Some computed data that should never change after construction. 11 | //! pub computed: Bar, 12 | //! 13 | //! /* some other fields */ 14 | //! } 15 | //! 16 | //! impl Bar { 17 | //! /// Mutate the `Bar`. 18 | //! pub fn mutate(&mut self) { } 19 | //! } 20 | //! ``` 21 | //! 22 | //! Now suppose we want to pass around a mutable `Foo` instance but, we want to make sure that 23 | //! `computed` does not change accidentally (e.g. somebody might accidentally call 24 | //! `foo.computed.mutate()`). This is what `Frozen` is for. We can do the following: 25 | //! 26 | //! ```rust 27 | //! use rustc_data_structures::frozen::Frozen; 28 | //! 29 | //! struct Foo { 30 | //! /// Some computed data that should never change after construction. 31 | //! pub computed: Frozen, 32 | //! 33 | //! /* some other fields */ 34 | //! } 35 | //! ``` 36 | //! 37 | //! `Frozen` impls `Deref`, so we can ergonomically call methods on `Bar`, but it doesn't `impl 38 | //! DerefMut`. Now calling `foo.compute.mutate()` will result in a compile-time error stating that 39 | //! `mutate` requires a mutable reference but we don't have one. 40 | //! 41 | //! # Caveats 42 | //! 43 | //! - `Frozen` doesn't try to defend against interior mutability (e.g. `Frozen>`). 44 | //! - `Frozen` doesn't pin it's contents (e.g. one could still do `foo.computed = 45 | //! Frozen::freeze(new_bar)`). 46 | 47 | /// An owned immutable value. 48 | #[derive(Debug)] 49 | pub struct Frozen(T); 50 | 51 | impl Frozen { 52 | pub fn freeze(val: T) -> Self { 53 | Frozen(val) 54 | } 55 | } 56 | 57 | impl std::ops::Deref for Frozen { 58 | type Target = T; 59 | 60 | fn deref(&self) -> &T { 61 | &self.0 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/binary_search_util/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests; 3 | 4 | /// Uses a sorted slice `data: &[E]` as a kind of "multi-map". The 5 | /// `key_fn` extracts a key of type `K` from the data, and this 6 | /// function finds the range of elements that match the key. `data` 7 | /// must have been sorted as if by a call to `sort_by_key` for this to 8 | /// work. 9 | pub fn binary_search_slice(data: &'d [E], key_fn: impl Fn(&E) -> K, key: &K) -> &'d [E] 10 | where 11 | K: Ord, 12 | { 13 | let mid = match data.binary_search_by_key(key, &key_fn) { 14 | Ok(mid) => mid, 15 | Err(_) => return &[], 16 | }; 17 | let size = data.len(); 18 | 19 | // We get back *some* element with the given key -- so do 20 | // a galloping search backwards to find the *first* one. 21 | let mut start = mid; 22 | let mut previous = mid; 23 | let mut step = 1; 24 | loop { 25 | start = start.saturating_sub(step); 26 | if start == 0 || key_fn(&data[start]) != *key { 27 | break; 28 | } 29 | previous = start; 30 | step *= 2; 31 | } 32 | step = previous - start; 33 | while step > 1 { 34 | let half = step / 2; 35 | let mid = start + half; 36 | if key_fn(&data[mid]) != *key { 37 | start = mid; 38 | } 39 | step -= half; 40 | } 41 | // adjust by one if we have overshot 42 | if start < size && key_fn(&data[start]) != *key { 43 | start += 1; 44 | } 45 | 46 | // Now search forward to find the *last* one. 47 | let mut end = mid; 48 | let mut previous = mid; 49 | let mut step = 1; 50 | loop { 51 | end = end.saturating_add(step).min(size); 52 | if end == size || key_fn(&data[end]) != *key { 53 | break; 54 | } 55 | previous = end; 56 | step *= 2; 57 | } 58 | step = end - previous; 59 | while step > 1 { 60 | let half = step / 2; 61 | let mid = end - half; 62 | if key_fn(&data[mid]) != *key { 63 | end = mid; 64 | } 65 | step -= half; 66 | } 67 | 68 | &data[start..end] 69 | } 70 | -------------------------------------------------------------------------------- /compiler/span/src/lev_distance/tests.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[test] 4 | fn test_lev_distance() { 5 | use std::char::{from_u32, MAX}; 6 | // Test bytelength agnosticity 7 | for c in (0..MAX as u32).filter_map(from_u32).map(|i| i.to_string()) { 8 | assert_eq!(lev_distance(&c[..], &c[..]), 0); 9 | } 10 | 11 | let a = "\nMäry häd ä little lämb\n\nLittle lämb\n"; 12 | let b = "\nMary häd ä little lämb\n\nLittle lämb\n"; 13 | let c = "Mary häd ä little lämb\n\nLittle lämb\n"; 14 | assert_eq!(lev_distance(a, b), 1); 15 | assert_eq!(lev_distance(b, a), 1); 16 | assert_eq!(lev_distance(a, c), 2); 17 | assert_eq!(lev_distance(c, a), 2); 18 | assert_eq!(lev_distance(b, c), 1); 19 | assert_eq!(lev_distance(c, b), 1); 20 | } 21 | 22 | #[test] 23 | fn test_find_best_match_for_name() { 24 | use crate::with_default_session_globals; 25 | with_default_session_globals(|| { 26 | let input = vec![Symbol::intern("aaab"), Symbol::intern("aaabc")]; 27 | assert_eq!( 28 | find_best_match_for_name(&input, Symbol::intern("aaaa"), None), 29 | Some(Symbol::intern("aaab")) 30 | ); 31 | 32 | assert_eq!(find_best_match_for_name(&input, Symbol::intern("1111111111"), None), None); 33 | 34 | let input = vec![Symbol::intern("aAAA")]; 35 | assert_eq!( 36 | find_best_match_for_name(&input, Symbol::intern("AAAA"), None), 37 | Some(Symbol::intern("aAAA")) 38 | ); 39 | 40 | let input = vec![Symbol::intern("AAAA")]; 41 | // Returns None because `lev_distance > max_dist / 3` 42 | assert_eq!(find_best_match_for_name(&input, Symbol::intern("aaaa"), None), None); 43 | 44 | let input = vec![Symbol::intern("AAAA")]; 45 | assert_eq!( 46 | find_best_match_for_name(&input, Symbol::intern("aaaa"), Some(4)), 47 | Some(Symbol::intern("AAAA")) 48 | ); 49 | 50 | let input = vec![Symbol::intern("a_longer_variable_name")]; 51 | assert_eq!( 52 | find_best_match_for_name(&input, Symbol::intern("a_variable_longer_name"), None), 53 | Some(Symbol::intern("a_longer_variable_name")) 54 | ); 55 | }) 56 | } 57 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/graph/tests.rs: -------------------------------------------------------------------------------- 1 | use crate::fx::FxHashMap; 2 | use std::cmp::max; 3 | use std::iter; 4 | use std::slice; 5 | 6 | use super::*; 7 | 8 | pub struct TestGraph { 9 | num_nodes: usize, 10 | start_node: usize, 11 | successors: FxHashMap>, 12 | predecessors: FxHashMap>, 13 | } 14 | 15 | impl TestGraph { 16 | pub fn new(start_node: usize, edges: &[(usize, usize)]) -> Self { 17 | let mut graph = TestGraph { 18 | num_nodes: start_node + 1, 19 | start_node, 20 | successors: FxHashMap::default(), 21 | predecessors: FxHashMap::default(), 22 | }; 23 | for &(source, target) in edges { 24 | graph.num_nodes = max(graph.num_nodes, source + 1); 25 | graph.num_nodes = max(graph.num_nodes, target + 1); 26 | graph.successors.entry(source).or_default().push(target); 27 | graph.predecessors.entry(target).or_default().push(source); 28 | } 29 | for node in 0..graph.num_nodes { 30 | graph.successors.entry(node).or_default(); 31 | graph.predecessors.entry(node).or_default(); 32 | } 33 | graph 34 | } 35 | } 36 | 37 | impl DirectedGraph for TestGraph { 38 | type Node = usize; 39 | } 40 | 41 | impl WithStartNode for TestGraph { 42 | fn start_node(&self) -> usize { 43 | self.start_node 44 | } 45 | } 46 | 47 | impl WithNumNodes for TestGraph { 48 | fn num_nodes(&self) -> usize { 49 | self.num_nodes 50 | } 51 | } 52 | 53 | impl WithPredecessors for TestGraph { 54 | fn predecessors(&self, node: usize) -> >::Iter { 55 | self.predecessors[&node].iter().cloned() 56 | } 57 | } 58 | 59 | impl WithSuccessors for TestGraph { 60 | fn successors(&self, node: usize) -> >::Iter { 61 | self.successors[&node].iter().cloned() 62 | } 63 | } 64 | 65 | impl<'graph> GraphPredecessors<'graph> for TestGraph { 66 | type Item = usize; 67 | type Iter = iter::Cloned>; 68 | } 69 | 70 | impl<'graph> GraphSuccessors<'graph> for TestGraph { 71 | type Item = usize; 72 | type Iter = iter::Cloned>; 73 | } 74 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/steal.rs: -------------------------------------------------------------------------------- 1 | use crate::stable_hasher::{HashStable, StableHasher}; 2 | use crate::sync::{MappedReadGuard, ReadGuard, RwLock}; 3 | 4 | /// The `Steal` struct is intended to used as the value for a query. 5 | /// Specifically, we sometimes have queries (*cough* MIR *cough*) 6 | /// where we create a large, complex value that we want to iteratively 7 | /// update (e.g., optimize). We could clone the value for each 8 | /// optimization, but that'd be expensive. And yet we don't just want 9 | /// to mutate it in place, because that would spoil the idea that 10 | /// queries are these pure functions that produce an immutable value 11 | /// (since if you did the query twice, you could observe the mutations). 12 | /// So instead we have the query produce a `&'tcx Steal>` 13 | /// (to be very specific). Now we can read from this 14 | /// as much as we want (using `borrow()`), but you can also 15 | /// `steal()`. Once you steal, any further attempt to read will panic. 16 | /// Therefore, we know that -- assuming no ICE -- nobody is observing 17 | /// the fact that the MIR was updated. 18 | /// 19 | /// Obviously, whenever you have a query that yields a `Steal` value, 20 | /// you must treat it with caution, and make sure that you know that 21 | /// -- once the value is stolen -- it will never be read from again. 22 | // 23 | // FIXME(#41710): what is the best way to model linear queries? 24 | #[derive(Debug)] 25 | pub struct Steal { 26 | value: RwLock>, 27 | } 28 | 29 | impl Steal { 30 | pub fn new(value: T) -> Self { 31 | Steal { value: RwLock::new(Some(value)) } 32 | } 33 | 34 | #[track_caller] 35 | pub fn borrow(&self) -> MappedReadGuard<'_, T> { 36 | ReadGuard::map(self.value.borrow(), |opt| match *opt { 37 | None => panic!("attempted to read from stolen value"), 38 | Some(ref v) => v, 39 | }) 40 | } 41 | 42 | #[track_caller] 43 | pub fn steal(&self) -> T { 44 | let value_ref = &mut *self.value.try_write().expect("stealing value which is locked"); 45 | let value = value_ref.take(); 46 | value.expect("attempt to steal from stolen value") 47 | } 48 | } 49 | 50 | impl> HashStable for Steal { 51 | fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { 52 | self.borrow().hash_stable(hcx, hasher); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/graph/mod.rs: -------------------------------------------------------------------------------- 1 | use rustc_index::vec::Idx; 2 | 3 | pub mod dominators; 4 | pub mod implementation; 5 | pub mod iterate; 6 | mod reference; 7 | pub mod scc; 8 | pub mod vec_graph; 9 | 10 | #[cfg(test)] 11 | mod tests; 12 | 13 | pub trait DirectedGraph { 14 | type Node: Idx; 15 | } 16 | 17 | pub trait WithNumNodes: DirectedGraph { 18 | fn num_nodes(&self) -> usize; 19 | } 20 | 21 | pub trait WithNumEdges: DirectedGraph { 22 | fn num_edges(&self) -> usize; 23 | } 24 | 25 | pub trait WithSuccessors: DirectedGraph 26 | where 27 | Self: for<'graph> GraphSuccessors<'graph, Item = ::Node>, 28 | { 29 | fn successors(&self, node: Self::Node) -> >::Iter; 30 | 31 | fn depth_first_search(&self, from: Self::Node) -> iterate::DepthFirstSearch<'_, Self> 32 | where 33 | Self: WithNumNodes, 34 | { 35 | iterate::DepthFirstSearch::new(self, from) 36 | } 37 | } 38 | 39 | #[allow(unused_lifetimes)] 40 | pub trait GraphSuccessors<'graph> { 41 | type Item; 42 | type Iter: Iterator; 43 | } 44 | 45 | pub trait WithPredecessors: DirectedGraph 46 | where 47 | Self: for<'graph> GraphPredecessors<'graph, Item = ::Node>, 48 | { 49 | fn predecessors(&self, node: Self::Node) -> >::Iter; 50 | } 51 | 52 | #[allow(unused_lifetimes)] 53 | pub trait GraphPredecessors<'graph> { 54 | type Item; 55 | type Iter: Iterator; 56 | } 57 | 58 | pub trait WithStartNode: DirectedGraph { 59 | fn start_node(&self) -> Self::Node; 60 | } 61 | 62 | pub trait ControlFlowGraph: 63 | DirectedGraph + WithStartNode + WithPredecessors + WithStartNode + WithSuccessors + WithNumNodes 64 | { 65 | // convenient trait 66 | } 67 | 68 | impl ControlFlowGraph for T where 69 | T: DirectedGraph 70 | + WithStartNode 71 | + WithPredecessors 72 | + WithStartNode 73 | + WithSuccessors 74 | + WithNumNodes 75 | { 76 | } 77 | 78 | /// Returns `true` if the graph has a cycle that is reachable from the start node. 79 | pub fn is_cyclic(graph: &G) -> bool 80 | where 81 | G: ?Sized + DirectedGraph + WithStartNode + WithSuccessors + WithNumNodes, 82 | { 83 | iterate::TriColorDepthFirstSearch::new(graph) 84 | .run_from_start(&mut iterate::CycleDetector) 85 | .is_some() 86 | } 87 | -------------------------------------------------------------------------------- /compiler/lexer/src/cursor.rs: -------------------------------------------------------------------------------- 1 | use std::str::Chars; 2 | 3 | /// Peekable iterator over a char sequence. 4 | /// 5 | /// Next characters can be peeked via `nth_char` method, 6 | /// and position can be shifted forward via `bump` method. 7 | pub(crate) struct Cursor<'a> { 8 | initial_len: usize, 9 | chars: Chars<'a>, 10 | #[cfg(debug_assertions)] 11 | prev: char, 12 | } 13 | 14 | pub(crate) const EOF_CHAR: char = '\0'; 15 | 16 | impl<'a> Cursor<'a> { 17 | pub(crate) fn new(input: &'a str) -> Cursor<'a> { 18 | Cursor { 19 | initial_len: input.len(), 20 | chars: input.chars(), 21 | #[cfg(debug_assertions)] 22 | prev: EOF_CHAR, 23 | } 24 | } 25 | 26 | /// Returns the last eaten symbol (or `'\0'` in release builds). 27 | /// (For debug assertions only.) 28 | pub(crate) fn prev(&self) -> char { 29 | #[cfg(debug_assertions)] 30 | { 31 | self.prev 32 | } 33 | 34 | #[cfg(not(debug_assertions))] 35 | { 36 | EOF_CHAR 37 | } 38 | } 39 | 40 | /// Returns nth character relative to the current cursor position. 41 | /// If requested position doesn't exist, `EOF_CHAR` is returned. 42 | /// However, getting `EOF_CHAR` doesn't always mean actual end of file, 43 | /// it should be checked with `is_eof` method. 44 | fn nth_char(&self, n: usize) -> char { 45 | self.chars().nth(n).unwrap_or(EOF_CHAR) 46 | } 47 | 48 | /// Peeks the next symbol from the input stream without consuming it. 49 | pub(crate) fn first(&self) -> char { 50 | self.nth_char(0) 51 | } 52 | 53 | /// Peeks the second symbol from the input stream without consuming it. 54 | pub(crate) fn second(&self) -> char { 55 | self.nth_char(1) 56 | } 57 | 58 | /// Checks if there is nothing more to consume. 59 | pub(crate) fn is_eof(&self) -> bool { 60 | self.chars.as_str().is_empty() 61 | } 62 | 63 | /// Returns amount of already consumed symbols. 64 | pub(crate) fn len_consumed(&self) -> usize { 65 | self.initial_len - self.chars.as_str().len() 66 | } 67 | 68 | /// Returns a `Chars` iterator over the remaining characters. 69 | fn chars(&self) -> Chars<'a> { 70 | self.chars.clone() 71 | } 72 | 73 | /// Moves to the next character. 74 | pub(crate) fn bump(&mut self) -> Option { 75 | let c = self.chars.next()?; 76 | 77 | #[cfg(debug_assertions)] 78 | { 79 | self.prev = c; 80 | } 81 | 82 | Some(c) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/functor.rs: -------------------------------------------------------------------------------- 1 | use rustc_index::vec::{Idx, IndexVec}; 2 | use std::mem; 3 | use std::ptr; 4 | 5 | pub trait IdFunctor { 6 | type Inner; 7 | 8 | fn map_id(self, f: F) -> Self 9 | where 10 | F: FnMut(Self::Inner) -> Self::Inner; 11 | } 12 | 13 | impl IdFunctor for Box { 14 | type Inner = T; 15 | 16 | #[inline] 17 | fn map_id(self, mut f: F) -> Self 18 | where 19 | F: FnMut(Self::Inner) -> Self::Inner, 20 | { 21 | let raw = Box::into_raw(self); 22 | unsafe { 23 | // SAFETY: The raw pointer points to a valid value of type `T`. 24 | let value = ptr::read(raw); 25 | // SAFETY: Converts `Box` to `Box>` which is the 26 | // inverse of `Box::assume_init()` and should be safe. 27 | let mut raw: Box> = Box::from_raw(raw.cast()); 28 | // SAFETY: Write the mapped value back into the `Box`. 29 | ptr::write(raw.as_mut_ptr(), f(value)); 30 | // SAFETY: We just initialized `raw`. 31 | raw.assume_init() 32 | } 33 | } 34 | } 35 | 36 | impl IdFunctor for Vec { 37 | type Inner = T; 38 | 39 | #[inline] 40 | fn map_id(mut self, mut f: F) -> Self 41 | where 42 | F: FnMut(Self::Inner) -> Self::Inner, 43 | { 44 | // FIXME: We don't really care about panics here and leak 45 | // far more than we should, but that should be fine for now. 46 | let len = self.len(); 47 | unsafe { 48 | self.set_len(0); 49 | let start = self.as_mut_ptr(); 50 | for i in 0..len { 51 | let p = start.add(i); 52 | ptr::write(p, f(ptr::read(p))); 53 | } 54 | self.set_len(len); 55 | } 56 | self 57 | } 58 | } 59 | 60 | impl IdFunctor for Box<[T]> { 61 | type Inner = T; 62 | 63 | #[inline] 64 | fn map_id(self, f: F) -> Self 65 | where 66 | F: FnMut(Self::Inner) -> Self::Inner, 67 | { 68 | Vec::from(self).map_id(f).into() 69 | } 70 | } 71 | 72 | impl IdFunctor for IndexVec { 73 | type Inner = T; 74 | 75 | #[inline] 76 | fn map_id(self, f: F) -> Self 77 | where 78 | F: FnMut(Self::Inner) -> Self::Inner, 79 | { 80 | IndexVec::from_raw(self.raw.map_id(f)) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/thin_vec.rs: -------------------------------------------------------------------------------- 1 | use crate::stable_hasher::{HashStable, StableHasher}; 2 | 3 | /// A vector type optimized for cases where this size is usually 0 (cf. `SmallVector`). 4 | /// The `Option>` wrapping allows us to represent a zero sized vector with `None`, 5 | /// which uses only a single (null) pointer. 6 | #[derive(Clone, Encodable, Decodable, Debug)] 7 | pub struct ThinVec(Option>>); 8 | 9 | impl ThinVec { 10 | pub fn new() -> Self { 11 | ThinVec(None) 12 | } 13 | } 14 | 15 | impl From> for ThinVec { 16 | fn from(vec: Vec) -> Self { 17 | if vec.is_empty() { ThinVec(None) } else { ThinVec(Some(Box::new(vec))) } 18 | } 19 | } 20 | 21 | impl Into> for ThinVec { 22 | fn into(self) -> Vec { 23 | match self { 24 | ThinVec(None) => Vec::new(), 25 | ThinVec(Some(vec)) => *vec, 26 | } 27 | } 28 | } 29 | 30 | impl ::std::ops::Deref for ThinVec { 31 | type Target = [T]; 32 | fn deref(&self) -> &[T] { 33 | match *self { 34 | ThinVec(None) => &[], 35 | ThinVec(Some(ref vec)) => vec, 36 | } 37 | } 38 | } 39 | 40 | impl ::std::ops::DerefMut for ThinVec { 41 | fn deref_mut(&mut self) -> &mut [T] { 42 | match *self { 43 | ThinVec(None) => &mut [], 44 | ThinVec(Some(ref mut vec)) => vec, 45 | } 46 | } 47 | } 48 | 49 | impl Extend for ThinVec { 50 | fn extend>(&mut self, iter: I) { 51 | match *self { 52 | ThinVec(Some(ref mut vec)) => vec.extend(iter), 53 | ThinVec(None) => *self = iter.into_iter().collect::>().into(), 54 | } 55 | } 56 | 57 | fn extend_one(&mut self, item: T) { 58 | match *self { 59 | ThinVec(Some(ref mut vec)) => vec.push(item), 60 | ThinVec(None) => *self = vec![item].into(), 61 | } 62 | } 63 | 64 | fn extend_reserve(&mut self, additional: usize) { 65 | match *self { 66 | ThinVec(Some(ref mut vec)) => vec.reserve(additional), 67 | ThinVec(None) => *self = Vec::with_capacity(additional).into(), 68 | } 69 | } 70 | } 71 | 72 | impl, CTX> HashStable for ThinVec { 73 | fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { 74 | (**self).hash_stable(hcx, hasher) 75 | } 76 | } 77 | 78 | impl Default for ThinVec { 79 | fn default() -> Self { 80 | Self(None) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/stable_hasher/tests.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | // The tests below compare the computed hashes to particular expected values 4 | // in order to test that we produce the same results on different platforms, 5 | // regardless of endianness and `usize` and `isize` size differences (this 6 | // of course assumes we run these tests on platforms that differ in those 7 | // ways). The expected values depend on the hashing algorithm used, so they 8 | // need to be updated whenever StableHasher changes its hashing algorithm. 9 | 10 | #[test] 11 | fn test_hash_integers() { 12 | // Test that integers are handled consistently across platforms. 13 | let test_u8 = 0xAB_u8; 14 | let test_u16 = 0xFFEE_u16; 15 | let test_u32 = 0x445577AA_u32; 16 | let test_u64 = 0x01234567_13243546_u64; 17 | let test_u128 = 0x22114433_66557788_99AACCBB_EEDDFF77_u128; 18 | let test_usize = 0xD0C0B0A0_usize; 19 | 20 | let test_i8 = -100_i8; 21 | let test_i16 = -200_i16; 22 | let test_i32 = -300_i32; 23 | let test_i64 = -400_i64; 24 | let test_i128 = -500_i128; 25 | let test_isize = -600_isize; 26 | 27 | let mut h = StableHasher::new(); 28 | test_u8.hash(&mut h); 29 | test_u16.hash(&mut h); 30 | test_u32.hash(&mut h); 31 | test_u64.hash(&mut h); 32 | test_u128.hash(&mut h); 33 | test_usize.hash(&mut h); 34 | test_i8.hash(&mut h); 35 | test_i16.hash(&mut h); 36 | test_i32.hash(&mut h); 37 | test_i64.hash(&mut h); 38 | test_i128.hash(&mut h); 39 | test_isize.hash(&mut h); 40 | 41 | // This depends on the hashing algorithm. See note at top of file. 42 | let expected = (2736651863462566372, 8121090595289675650); 43 | 44 | assert_eq!(h.finalize(), expected); 45 | } 46 | 47 | #[test] 48 | fn test_hash_usize() { 49 | // Test that usize specifically is handled consistently across platforms. 50 | let test_usize = 0xABCDEF01_usize; 51 | 52 | let mut h = StableHasher::new(); 53 | test_usize.hash(&mut h); 54 | 55 | // This depends on the hashing algorithm. See note at top of file. 56 | let expected = (5798740672699530587, 11186240177685111648); 57 | 58 | assert_eq!(h.finalize(), expected); 59 | } 60 | 61 | #[test] 62 | fn test_hash_isize() { 63 | // Test that isize specifically is handled consistently across platforms. 64 | let test_isize = -7_isize; 65 | 66 | let mut h = StableHasher::new(); 67 | test_isize.hash(&mut h); 68 | 69 | // This depends on the hashing algorithm. See note at top of file. 70 | let expected = (14721296605626097289, 11385941877786388409); 71 | 72 | assert_eq!(h.finalize(), expected); 73 | } 74 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/stable_map.rs: -------------------------------------------------------------------------------- 1 | pub use rustc_hash::FxHashMap; 2 | use std::borrow::Borrow; 3 | use std::collections::hash_map::Entry; 4 | use std::fmt; 5 | use std::hash::Hash; 6 | 7 | /// A deterministic wrapper around FxHashMap that does not provide iteration support. 8 | /// 9 | /// It supports insert, remove, get and get_mut functions from FxHashMap. 10 | /// It also allows to convert hashmap to a sorted vector with the method `into_sorted_vector()`. 11 | #[derive(Clone)] 12 | pub struct StableMap { 13 | base: FxHashMap, 14 | } 15 | 16 | impl Default for StableMap 17 | where 18 | K: Eq + Hash, 19 | { 20 | fn default() -> StableMap { 21 | StableMap::new() 22 | } 23 | } 24 | 25 | impl fmt::Debug for StableMap 26 | where 27 | K: Eq + Hash + fmt::Debug, 28 | V: fmt::Debug, 29 | { 30 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 31 | write!(f, "{:?}", self.base) 32 | } 33 | } 34 | 35 | impl PartialEq for StableMap 36 | where 37 | K: Eq + Hash, 38 | V: PartialEq, 39 | { 40 | fn eq(&self, other: &StableMap) -> bool { 41 | self.base == other.base 42 | } 43 | } 44 | 45 | impl Eq for StableMap 46 | where 47 | K: Eq + Hash, 48 | V: Eq, 49 | { 50 | } 51 | 52 | impl StableMap 53 | where 54 | K: Eq + Hash, 55 | { 56 | pub fn new() -> StableMap { 57 | StableMap { base: FxHashMap::default() } 58 | } 59 | 60 | pub fn into_sorted_vector(self) -> Vec<(K, V)> 61 | where 62 | K: Ord + Copy, 63 | { 64 | let mut vector = self.base.into_iter().collect::>(); 65 | vector.sort_unstable_by_key(|pair| pair.0); 66 | vector 67 | } 68 | 69 | pub fn entry(&mut self, k: K) -> Entry<'_, K, V> { 70 | self.base.entry(k) 71 | } 72 | 73 | pub fn get(&self, k: &Q) -> Option<&V> 74 | where 75 | K: Borrow, 76 | Q: Hash + Eq, 77 | { 78 | self.base.get(k) 79 | } 80 | 81 | pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> 82 | where 83 | K: Borrow, 84 | Q: Hash + Eq, 85 | { 86 | self.base.get_mut(k) 87 | } 88 | 89 | pub fn insert(&mut self, k: K, v: V) -> Option { 90 | self.base.insert(k, v) 91 | } 92 | 93 | pub fn remove(&mut self, k: &Q) -> Option 94 | where 95 | K: Borrow, 96 | Q: Hash + Eq, 97 | { 98 | self.base.remove(k) 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /compiler/ast/src/ast/class.rs: -------------------------------------------------------------------------------- 1 | use crate::ptr::P; 2 | use crate::token::{self, CommentKind, DelimToken, Token}; 3 | use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream, TokenTree}; 4 | 5 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; 6 | use rustc_data_structures::stack::ensure_sufficient_stack; 7 | use rustc_data_structures::sync::Lrc; 8 | use rustc_data_structures::thin_vec::ThinVec; 9 | use rustc_macros::HashStable_Generic; 10 | use rustc_serialize::{self, Decoder, Encoder}; 11 | use tscore_span::source_map::{respan, Spanned}; 12 | use tscore_span::symbol::{kw, sym, Ident, Symbol}; 13 | use tscore_span::{Span, DUMMY_SP}; 14 | 15 | use super::{Block, Decorator, Expr, ExprWithTypeArgs, Fn, Generics, JSDoc, Lit, Pat, Ty}; 16 | 17 | use std::cmp::Ordering; 18 | use std::convert::TryFrom; 19 | use std::fmt; 20 | 21 | #[derive(Clone, Encodable, Decodable, Debug)] 22 | pub enum PropName { 23 | Ident(Ident), 24 | /// only StrLit and NumLit available 25 | NumLit(Lit), 26 | Expr(P), 27 | /// `#name` 28 | PrivateIdent(Ident), 29 | } 30 | 31 | #[derive(Clone, Encodable, Decodable, Debug)] 32 | pub struct Prop { 33 | pub name: Ident, 34 | pub ty: Option, 35 | pub init: Option, 36 | pub decorators: Vec, 37 | pub span: Span, 38 | } 39 | 40 | #[derive(Clone, Encodable, Decodable, Debug)] 41 | pub enum ClassElementKind { 42 | /// ES6 allows these as class elements. 43 | Semi, 44 | /// separate constructor from normal method for potential processing 45 | Constructor(P), 46 | Getter(P), 47 | Setter(P), 48 | IndexSig(P), 49 | Method(P), 50 | Property(P), 51 | } 52 | 53 | #[derive(Clone, Encodable, Decodable, Debug)] 54 | pub enum Visibility { 55 | Public, 56 | Protected, 57 | Private, 58 | } 59 | 60 | #[derive(Clone, Encodable, Decodable, Debug)] 61 | pub struct ClassElement { 62 | pub kind: ClassElementKind, 63 | pub vis: Visibility, 64 | pub name: PropName, 65 | pub is_static: bool, 66 | pub is_abstract: bool, 67 | pub definite: bool, 68 | pub optional: bool, 69 | pub readonly: bool, 70 | pub span: Span, 71 | } 72 | 73 | #[derive(Clone, Encodable, Decodable, Debug)] 74 | pub enum Heritage { 75 | Extends(ExprWithTypeArgs), 76 | Impl(ExprWithTypeArgs), 77 | } 78 | 79 | #[derive(Clone, Encodable, Decodable, Debug)] 80 | pub struct Class { 81 | /// May be optional in `export default class { ... }`. 82 | pub name: Option, 83 | pub generics: Generics, 84 | pub heritages: Vec, 85 | pub span: Span, 86 | pub elementss: Vec, 87 | pub is_abstract: bool, 88 | pub decorators: Vec, 89 | } 90 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/tiny_list.rs: -------------------------------------------------------------------------------- 1 | //! A singly-linked list. 2 | //! 3 | //! Using this data structure only makes sense under very specific 4 | //! circumstances: 5 | //! 6 | //! - If you have a list that rarely stores more than one element, then this 7 | //! data-structure can store the element without allocating and only uses as 8 | //! much space as a `Option<(T, usize)>`. If T can double as the `Option` 9 | //! discriminant, it will even only be as large as `T, usize`. 10 | //! 11 | //! If you expect to store more than 1 element in the common case, steer clear 12 | //! and use a `Vec`, `Box<[T]>`, or a `SmallVec`. 13 | 14 | #[cfg(test)] 15 | mod tests; 16 | 17 | #[derive(Clone)] 18 | pub struct TinyList { 19 | head: Option>, 20 | } 21 | 22 | impl TinyList { 23 | #[inline] 24 | pub fn new() -> TinyList { 25 | TinyList { head: None } 26 | } 27 | 28 | #[inline] 29 | pub fn new_single(data: T) -> TinyList { 30 | TinyList { head: Some(Element { data, next: None }) } 31 | } 32 | 33 | #[inline] 34 | pub fn insert(&mut self, data: T) { 35 | self.head = Some(Element { data, next: self.head.take().map(Box::new) }); 36 | } 37 | 38 | #[inline] 39 | pub fn remove(&mut self, data: &T) -> bool { 40 | self.head = match self.head { 41 | Some(ref mut head) if head.data == *data => head.next.take().map(|x| *x), 42 | Some(ref mut head) => return head.remove_next(data), 43 | None => return false, 44 | }; 45 | true 46 | } 47 | 48 | #[inline] 49 | pub fn contains(&self, data: &T) -> bool { 50 | let mut elem = self.head.as_ref(); 51 | while let Some(ref e) = elem { 52 | if &e.data == data { 53 | return true; 54 | } 55 | elem = e.next.as_deref(); 56 | } 57 | false 58 | } 59 | 60 | #[inline] 61 | pub fn len(&self) -> usize { 62 | let (mut elem, mut count) = (self.head.as_ref(), 0); 63 | while let Some(ref e) = elem { 64 | count += 1; 65 | elem = e.next.as_deref(); 66 | } 67 | count 68 | } 69 | } 70 | 71 | #[derive(Clone)] 72 | struct Element { 73 | data: T, 74 | next: Option>>, 75 | } 76 | 77 | impl Element { 78 | fn remove_next(&mut self, data: &T) -> bool { 79 | let mut n = self; 80 | loop { 81 | match n.next { 82 | Some(ref mut next) if next.data == *data => { 83 | n.next = next.next.take(); 84 | return true; 85 | } 86 | Some(ref mut next) => n = next, 87 | None => return false, 88 | } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /compiler/parser/src/context.rs: -------------------------------------------------------------------------------- 1 | #[rustfmt::skip] 2 | pub enum ParsingContext { 3 | SourceElements, // Elements in source file 4 | BlockStatements, // Statements in block 5 | SwitchClauses, // Clauses in switch statement 6 | SwitchClauseStatements, // Statements in switch clause 7 | TypeMembers, // Members in interface or type literal 8 | ClassMembers, // Members in class declaration 9 | EnumMembers, // Members in enum declaration 10 | HeritageClauseElement, // Elements in a heritage clause 11 | VariableDeclarations, // Variable declarations in variable statement 12 | ObjectBindingElements, // Binding elements in object binding list 13 | ArrayBindingElements, // Binding elements in array binding list 14 | ArgumentExpressions, // Expressions in argument list 15 | ObjectLiteralMembers, // Members in object literal 16 | JsxAttributes, // Attributes in jsx element 17 | JsxChildren, // Things between opening and closing JSX tags 18 | ArrayLiteralMembers, // Members in array literal 19 | Parameters, // Parameters in parameter list 20 | JSDocParameters, // JSDoc parameters in parameter list of JSDoc function type 21 | RestProperties, // Property names in a rest type list 22 | TypeParameters, // Type parameters in type parameter list 23 | TypeArguments, // Type arguments in type argument list 24 | TupleElementTypes, // Element types in tuple element type list 25 | HeritageClauses, // Heritage clauses for a class or interface declaration. 26 | ImportOrExportSpecifiers, // Named import clause's import specifier list 27 | Count // Number of parsing contexts 28 | } 29 | 30 | pub mod TokenFlags { 31 | pub const None: u16 = 0; 32 | pub const PrecedingLineBreak: u16 = 1 << 0; 33 | pub const PrecedingJSDocComment: u16 = 1 << 1; 34 | pub const Unterminated: u16 = 1 << 2; 35 | pub const ExtendedUnicodeEscape: u16 = 1 << 3; 36 | pub const Scientific: u16 = 1 << 4; // e.g. `10e2` 37 | pub const Octal: u16 = 1 << 5; // e.g. `0777` 38 | pub const HexSpecifier: u16 = 1 << 6; // e.g. `0x00000000` 39 | pub const BinarySpecifier: u16 = 1 << 7; // e.g. `0b0110010000000000` 40 | pub const OctalSpecifier: u16 = 1 << 8; // e.g. `0o777` 41 | pub const ContainsSeparator: u16 = 1 << 9; // e.g. `0b1100_0101` 42 | pub const UnicodeEscape: u16 = 1 << 10; 43 | pub const ContainsInvalidEscape: u16 = 1 << 11; // e.g. `\uhello` 44 | pub const BinaryOrOctalSpecifier: u16 = BinarySpecifier | OctalSpecifier; 45 | pub const NumericLiteralFlags: u16 = 46 | Scientific | Octal | HexSpecifier | BinaryOrOctalSpecifier | ContainsSeparator; 47 | pub const TemplateLiteralLikeFlags: u16 = ContainsInvalidEscape | ContainsInvalidEscape; 48 | } 49 | -------------------------------------------------------------------------------- /compiler/ast/src/ast/lit.rs: -------------------------------------------------------------------------------- 1 | use super::{Expr, Fn, PropName}; 2 | use crate::ptr::P; 3 | use crate::token::{self, CommentKind, DelimToken, Token}; 4 | use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream, TokenTree}; 5 | 6 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; 7 | use rustc_data_structures::stack::ensure_sufficient_stack; 8 | use rustc_data_structures::sync::Lrc; 9 | use rustc_data_structures::thin_vec::ThinVec; 10 | use rustc_macros::HashStable_Generic; 11 | use rustc_serialize::{self, Decoder, Encoder}; 12 | use tscore_span::source_map::{respan, Spanned}; 13 | use tscore_span::symbol::{kw, sym, Ident, Symbol}; 14 | use tscore_span::{Span, DUMMY_SP}; 15 | 16 | use std::cmp::Ordering; 17 | use std::convert::TryFrom; 18 | use std::fmt; 19 | 20 | #[derive(Clone, Encodable, Decodable, Debug)] 21 | pub enum LitKind { 22 | /// `"foo"` 23 | Str(Symbol), 24 | /// `1` 25 | Num(f64), 26 | /// `true` 27 | Bool(bool), 28 | /// `\`foo${bar}\`` 29 | Template(P), 30 | /// `1n` 31 | BitInt, 32 | /// `/[a-z]/g` 33 | RegExp, 34 | /// `null` 35 | Null, 36 | Array(P), 37 | Object(P), 38 | } 39 | 40 | #[derive(Clone, Encodable, Decodable, Debug)] 41 | pub struct Lit { 42 | pub token: token::Lit, 43 | pub kind: LitKind, 44 | pub span: Span, 45 | } 46 | 47 | /// Same as `Lit` but restricted t ostring literals. 48 | #[derive(Clone, Copy, Encodable, Decodable, Debug)] 49 | pub struct StrLit { 50 | pub span: Span, 51 | pub symbol: Symbol, 52 | } 53 | 54 | #[derive(Clone, Encodable, Decodable, Debug)] 55 | pub struct TemplateSpan { 56 | pub span: Span, 57 | pub expr: P, 58 | pub lit: Option, 59 | } 60 | 61 | #[derive(Clone, Encodable, Decodable, Debug)] 62 | pub struct TemplateLit { 63 | pub span: Span, 64 | pub head: Option, 65 | pub spans: Vec>, 66 | } 67 | 68 | #[derive(Clone, Copy, Encodable, Decodable, Debug)] 69 | pub struct NumLit { 70 | pub span: Span, 71 | pub value: f64, 72 | } 73 | 74 | #[derive(Clone, Encodable, Decodable, Debug)] 75 | pub struct ObjectLit { 76 | pub multi_line: bool, 77 | pub props: Vec>, 78 | } 79 | 80 | #[derive(Clone, Encodable, Decodable, Debug)] 81 | pub struct ObjectLitEl { 82 | pub kind: ObjectLitElKind, 83 | pub span: Span, 84 | } 85 | 86 | #[derive(Clone, Encodable, Decodable, Debug)] 87 | pub struct PropAssign { 88 | pub span: Span, 89 | pub name: PropName, 90 | pub optional: bool, 91 | pub definite: bool, 92 | pub init: P, 93 | } 94 | 95 | #[derive(Clone, Encodable, Decodable, Debug)] 96 | pub enum ObjectLitElKind { 97 | PropAssign(P), 98 | ShortPropAssign(P), 99 | SpreadAssign(P), 100 | MethodDecl(P), 101 | Getter(P), 102 | Setter(P), 103 | } 104 | 105 | #[derive(Clone, Encodable, Decodable, Debug)] 106 | pub struct ArrayLit { 107 | pub elements: Vec>, 108 | pub multi_line: bool, 109 | } 110 | -------------------------------------------------------------------------------- /rustc/rustc_macros/src/symbols/tests.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | // This test is mainly here for interactive development. Use this test while 4 | // you're working on the proc-macro defined in this file. 5 | #[test] 6 | fn test_symbols() { 7 | // We textually include the symbol.rs file, which contains the list of all 8 | // symbols, keywords, and common words. Then we search for the 9 | // `symbols! { ... }` call. 10 | 11 | static SYMBOL_RS_FILE: &str = include_str!("../../../../compiler/span/src/symbol.rs"); 12 | 13 | let file = syn::parse_file(SYMBOL_RS_FILE).unwrap(); 14 | let symbols_path: syn::Path = syn::parse_quote!(symbols); 15 | 16 | let m: &syn::ItemMacro = file 17 | .items 18 | .iter() 19 | .filter_map(|i| { 20 | if let syn::Item::Macro(m) = i { 21 | if m.mac.path == symbols_path { Some(m) } else { None } 22 | } else { 23 | None 24 | } 25 | }) 26 | .next() 27 | .expect("did not find `symbols!` macro invocation."); 28 | 29 | let body_tokens = m.mac.tokens.clone(); 30 | 31 | test_symbols_macro(body_tokens, &[]); 32 | } 33 | 34 | fn test_symbols_macro(input: TokenStream, expected_errors: &[&str]) { 35 | let (output, found_errors) = symbols_with_errors(input); 36 | 37 | // It should always parse. 38 | let _parsed_file = syn::parse2::(output).unwrap(); 39 | 40 | assert_eq!( 41 | found_errors.len(), 42 | expected_errors.len(), 43 | "Macro generated a different number of errors than expected" 44 | ); 45 | 46 | for (found_error, &expected_error) in found_errors.iter().zip(expected_errors.iter()) { 47 | let found_error_str = format!("{}", found_error); 48 | assert_eq!(found_error_str, expected_error); 49 | } 50 | } 51 | 52 | #[test] 53 | fn check_dup_keywords() { 54 | let input = quote! { 55 | Keywords { 56 | Crate: "crate", 57 | Crate: "crate", 58 | } 59 | Symbols {} 60 | }; 61 | test_symbols_macro(input, &["Symbol `crate` is duplicated", "location of previous definition"]); 62 | } 63 | 64 | #[test] 65 | fn check_dup_symbol() { 66 | let input = quote! { 67 | Keywords {} 68 | Symbols { 69 | splat, 70 | splat, 71 | } 72 | }; 73 | test_symbols_macro(input, &["Symbol `splat` is duplicated", "location of previous definition"]); 74 | } 75 | 76 | #[test] 77 | fn check_dup_symbol_and_keyword() { 78 | let input = quote! { 79 | Keywords { 80 | Splat: "splat", 81 | } 82 | Symbols { 83 | splat, 84 | } 85 | }; 86 | test_symbols_macro(input, &["Symbol `splat` is duplicated", "location of previous definition"]); 87 | } 88 | 89 | #[test] 90 | fn check_symbol_order() { 91 | let input = quote! { 92 | Keywords {} 93 | Symbols { 94 | zebra, 95 | aardvark, 96 | } 97 | }; 98 | test_symbols_macro( 99 | input, 100 | &["Symbol `aardvark` must precede `zebra`", "location of previous symbol `zebra`"], 101 | ); 102 | } 103 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/obligation_forest/graphviz.rs: -------------------------------------------------------------------------------- 1 | use crate::obligation_forest::{ForestObligation, ObligationForest}; 2 | use rustc_graphviz as dot; 3 | use std::env::var_os; 4 | use std::fs::File; 5 | use std::io::BufWriter; 6 | use std::path::Path; 7 | use std::sync::atomic::AtomicUsize; 8 | use std::sync::atomic::Ordering; 9 | 10 | impl ObligationForest { 11 | /// Creates a graphviz representation of the obligation forest. Given a directory this will 12 | /// create files with name of the format `_.gv`. The counter is 13 | /// global and is maintained internally. 14 | /// 15 | /// Calling this will do nothing unless the environment variable 16 | /// `DUMP_OBLIGATION_FOREST_GRAPHVIZ` is defined. 17 | /// 18 | /// A few post-processing that you might want to do make the forest easier to visualize: 19 | /// 20 | /// * `sed 's,std::[a-z]*::,,g'` — Deletes the `std::::` prefix of paths. 21 | /// * `sed 's,"Binder(TraitPredicate(<\(.*\)>)) (\([^)]*\))","\1 (\2)",'` — Transforms 22 | /// `Binder(TraitPredicate())` into just ``. 23 | #[allow(dead_code)] 24 | pub fn dump_graphviz>(&self, dir: P, description: &str) { 25 | static COUNTER: AtomicUsize = AtomicUsize::new(0); 26 | 27 | if var_os("DUMP_OBLIGATION_FOREST_GRAPHVIZ").is_none() { 28 | return; 29 | } 30 | 31 | let counter = COUNTER.fetch_add(1, Ordering::AcqRel); 32 | 33 | let file_path = dir.as_ref().join(format!("{:010}_{}.gv", counter, description)); 34 | 35 | let mut gv_file = BufWriter::new(File::create(file_path).unwrap()); 36 | 37 | dot::render(&self, &mut gv_file).unwrap(); 38 | } 39 | } 40 | 41 | impl<'a, O: ForestObligation + 'a> dot::Labeller<'a> for &'a ObligationForest { 42 | type Node = usize; 43 | type Edge = (usize, usize); 44 | 45 | fn graph_id(&self) -> dot::Id<'_> { 46 | dot::Id::new("trait_obligation_forest").unwrap() 47 | } 48 | 49 | fn node_id(&self, index: &Self::Node) -> dot::Id<'_> { 50 | dot::Id::new(format!("obligation_{}", index)).unwrap() 51 | } 52 | 53 | fn node_label(&self, index: &Self::Node) -> dot::LabelText<'_> { 54 | let node = &self.nodes[*index]; 55 | let label = format!("{:?} ({:?})", node.obligation.as_cache_key(), node.state.get()); 56 | 57 | dot::LabelText::LabelStr(label.into()) 58 | } 59 | 60 | fn edge_label(&self, (_index_source, _index_target): &Self::Edge) -> dot::LabelText<'_> { 61 | dot::LabelText::LabelStr("".into()) 62 | } 63 | } 64 | 65 | impl<'a, O: ForestObligation + 'a> dot::GraphWalk<'a> for &'a ObligationForest { 66 | type Node = usize; 67 | type Edge = (usize, usize); 68 | 69 | fn nodes(&self) -> dot::Nodes<'_, Self::Node> { 70 | (0..self.nodes.len()).collect() 71 | } 72 | 73 | fn edges(&self) -> dot::Edges<'_, Self::Edge> { 74 | (0..self.nodes.len()) 75 | .flat_map(|i| { 76 | let node = &self.nodes[i]; 77 | 78 | node.dependents.iter().map(move |&d| (d, i)) 79 | }) 80 | .collect() 81 | } 82 | 83 | fn source(&self, (s, _): &Self::Edge) -> Self::Node { 84 | *s 85 | } 86 | 87 | fn target(&self, (_, t): &Self::Edge) -> Self::Node { 88 | *t 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /rustc/rustc_serialize/tests/leb128.rs: -------------------------------------------------------------------------------- 1 | #![feature(int_bits_const)] 2 | #![feature(maybe_uninit_slice)] 3 | #![feature(maybe_uninit_uninit_array)] 4 | 5 | use rustc_serialize::leb128::*; 6 | use std::mem::MaybeUninit; 7 | 8 | macro_rules! impl_test_unsigned_leb128 { 9 | ($test_name:ident, $write_fn_name:ident, $read_fn_name:ident, $int_ty:ident) => { 10 | #[test] 11 | fn $test_name() { 12 | // Test 256 evenly spaced values of integer range, 13 | // integer max value, and some "random" numbers. 14 | let mut values = Vec::new(); 15 | 16 | let increment = (1 as $int_ty) << ($int_ty::BITS - 8); 17 | values.extend((0..256).map(|i| $int_ty::MIN + i * increment)); 18 | 19 | values.push($int_ty::MAX); 20 | 21 | values 22 | .extend((-500..500).map(|i| (i as $int_ty).wrapping_mul(0x12345789ABCDEFu64 as $int_ty))); 23 | 24 | let mut stream = Vec::new(); 25 | 26 | for &x in &values { 27 | let mut buf = MaybeUninit::uninit_array(); 28 | stream.extend($write_fn_name(&mut buf, x)); 29 | } 30 | 31 | let mut position = 0; 32 | for &expected in &values { 33 | let (actual, bytes_read) = $read_fn_name(&stream[position..]); 34 | assert_eq!(expected, actual); 35 | position += bytes_read; 36 | } 37 | assert_eq!(stream.len(), position); 38 | } 39 | }; 40 | } 41 | 42 | impl_test_unsigned_leb128!(test_u16_leb128, write_u16_leb128, read_u16_leb128, u16); 43 | impl_test_unsigned_leb128!(test_u32_leb128, write_u32_leb128, read_u32_leb128, u32); 44 | impl_test_unsigned_leb128!(test_u64_leb128, write_u64_leb128, read_u64_leb128, u64); 45 | impl_test_unsigned_leb128!(test_u128_leb128, write_u128_leb128, read_u128_leb128, u128); 46 | impl_test_unsigned_leb128!(test_usize_leb128, write_usize_leb128, read_usize_leb128, usize); 47 | 48 | macro_rules! impl_test_signed_leb128 { 49 | ($test_name:ident, $write_fn_name:ident, $read_fn_name:ident, $int_ty:ident) => { 50 | #[test] 51 | fn $test_name() { 52 | // Test 256 evenly spaced values of integer range, 53 | // integer max value, and some "random" numbers. 54 | let mut values = Vec::new(); 55 | 56 | let mut value = $int_ty::MIN; 57 | let increment = (1 as $int_ty) << ($int_ty::BITS - 8); 58 | 59 | for _ in 0..256 { 60 | values.push(value); 61 | // The addition in the last loop iteration overflows. 62 | value = value.wrapping_add(increment); 63 | } 64 | 65 | values.push($int_ty::MAX); 66 | 67 | values 68 | .extend((-500..500).map(|i| (i as $int_ty).wrapping_mul(0x12345789ABCDEFi64 as $int_ty))); 69 | 70 | let mut stream = Vec::new(); 71 | 72 | for &x in &values { 73 | let mut buf = MaybeUninit::uninit_array(); 74 | stream.extend($write_fn_name(&mut buf, x)); 75 | } 76 | 77 | let mut position = 0; 78 | for &expected in &values { 79 | let (actual, bytes_read) = $read_fn_name(&stream[position..]); 80 | assert_eq!(expected, actual); 81 | position += bytes_read; 82 | } 83 | assert_eq!(stream.len(), position); 84 | } 85 | }; 86 | } 87 | 88 | impl_test_signed_leb128!(test_i16_leb128, write_i16_leb128, read_i16_leb128, i16); 89 | impl_test_signed_leb128!(test_i32_leb128, write_i32_leb128, read_i32_leb128, i32); 90 | impl_test_signed_leb128!(test_i64_leb128, write_i64_leb128, read_i64_leb128, i64); 91 | impl_test_signed_leb128!(test_i128_leb128, write_i128_leb128, read_i128_leb128, i128); 92 | impl_test_signed_leb128!(test_isize_leb128, write_isize_leb128, read_isize_leb128, isize); 93 | -------------------------------------------------------------------------------- /compiler/common/src/types.rs: -------------------------------------------------------------------------------- 1 | pub struct TsConfigSourceFile { 2 | pub extended_source_files: Vec, 3 | } 4 | 5 | #[repr(u8)] 6 | #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] 7 | pub enum ImportsNotUsedAsValues { 8 | Remove, 9 | Preserve, 10 | Error, 11 | } 12 | 13 | #[repr(u8)] 14 | #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] 15 | pub enum JsxEmit { 16 | None = 0, 17 | Preserve = 1, 18 | React = 2, 19 | ReactNative = 3, 20 | } 21 | 22 | #[repr(u8)] 23 | #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] 24 | pub enum ScriptKind { 25 | Unknown = 0, 26 | JS = 1, 27 | JSX = 2, 28 | TS = 3, 29 | TSX = 4, 30 | External = 5, 31 | JSON = 6, 32 | /** 33 | * Used on extensions that doesn't define the ScriptKind but the content defines it. 34 | * Deferred extensions are going to be included in all project contexts. 35 | */ 36 | Deferred = 7, 37 | } 38 | 39 | impl From<&str> for ScriptKind { 40 | fn from(file_name: &str) -> Self { 41 | match &file_name[file_name.rfind('.').unwrap_or(file_name.len() - 1)..] { 42 | ".js" => ScriptKind::JS, 43 | ".jsx" => ScriptKind::JSX, 44 | ".ts" => ScriptKind::TS, 45 | ".tsx" => ScriptKind::TSX, 46 | ".json" => ScriptKind::JSON, 47 | _ => ScriptKind::Unknown, 48 | } 49 | } 50 | } 51 | 52 | impl ScriptKind { 53 | pub fn ensure_script_kind(file_name: &str, script_kind: Option) -> ScriptKind { 54 | script_kind.unwrap_or_else(|| match ScriptKind::from(file_name) { 55 | ScriptKind::Unknown => ScriptKind::TS, 56 | k => k, 57 | }) 58 | } 59 | } 60 | 61 | #[repr(u8)] 62 | #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] 63 | pub enum ScriptTarget { 64 | ES3 = 0, 65 | ES5 = 1, 66 | ES2015 = 2, 67 | ES2016 = 3, 68 | ES2017 = 4, 69 | ES2018 = 5, 70 | ES2019 = 6, 71 | ES2020 = 7, 72 | ESNext = 99, 73 | JSON = 100, 74 | } 75 | 76 | impl Default for ScriptTarget { 77 | fn default() -> ScriptTarget { 78 | ScriptTarget::ESNext 79 | } 80 | } 81 | 82 | #[repr(u8)] 83 | #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] 84 | pub enum LanguageVariant { 85 | Standard, 86 | JSX, 87 | } 88 | 89 | impl Default for LanguageVariant { 90 | fn default() -> LanguageVariant { 91 | LanguageVariant::Standard 92 | } 93 | } 94 | 95 | impl From for LanguageVariant { 96 | fn from(kind: ScriptKind) -> Self { 97 | match kind { 98 | ScriptKind::TSX | ScriptKind::JSX | ScriptKind::JS | ScriptKind::JSON => LanguageVariant::JSX, 99 | _ => LanguageVariant::Standard, 100 | } 101 | } 102 | } 103 | 104 | #[repr(u8)] 105 | #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] 106 | pub enum ModuleKind { 107 | None = 0, 108 | CommonJS = 1, 109 | AMD = 2, 110 | UMD = 3, 111 | System = 4, 112 | 113 | // NOTE: ES module kinds should be contiguous to more easily check whether a module kind is *any* ES module kind. 114 | // Non-ES module kinds should not come between ES2015 (the earliest ES module kind) and ESNext (the last ES 115 | // module kind). 116 | ES2015 = 5, 117 | ES2020 = 6, 118 | ESNext = 99, 119 | } 120 | 121 | #[repr(u8)] 122 | #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] 123 | pub enum ModuleResolutionKind { 124 | Classic = 1, 125 | NodeJs = 2, 126 | } 127 | 128 | #[repr(u8)] 129 | #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] 130 | pub enum NewLineKind { 131 | CarriageReturnLineFeed, 132 | LineFeed, 133 | } 134 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Various data structures used by the Rust compiler. The intention 2 | //! is that code in here should be not be *specific* to rustc, so that 3 | //! it can be easily unit tested and so forth. 4 | //! 5 | //! # Note 6 | //! 7 | //! This API is completely unstable and subject to change. 8 | 9 | #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] 10 | #![feature(array_windows)] 11 | #![feature(control_flow_enum)] 12 | #![feature(in_band_lifetimes)] 13 | #![feature(unboxed_closures)] 14 | #![feature(generator_trait)] 15 | #![feature(fn_traits)] 16 | #![feature(int_bits_const)] 17 | #![feature(min_specialization)] 18 | #![feature(auto_traits)] 19 | #![feature(nll)] 20 | #![feature(allow_internal_unstable)] 21 | #![feature(hash_raw_entry)] 22 | #![feature(stmt_expr_attributes)] 23 | #![feature(core_intrinsics)] 24 | #![feature(test)] 25 | #![feature(associated_type_bounds)] 26 | #![feature(thread_id_value)] 27 | #![feature(extend_one)] 28 | #![feature(const_panic)] 29 | #![feature(new_uninit)] 30 | #![feature(once_cell)] 31 | #![feature(maybe_uninit_uninit_array)] 32 | #![allow(rustc::default_hash_types)] 33 | #![deny(unaligned_references)] 34 | 35 | #[macro_use] 36 | extern crate tracing; 37 | #[macro_use] 38 | extern crate cfg_if; 39 | #[macro_use] 40 | extern crate rustc_macros; 41 | 42 | #[inline(never)] 43 | #[cold] 44 | pub fn cold_path R, R>(f: F) -> R { 45 | f() 46 | } 47 | 48 | #[macro_export] 49 | macro_rules! likely { 50 | ($e:expr) => { 51 | match $e { 52 | #[allow(unused_unsafe)] 53 | e => unsafe { std::intrinsics::likely(e) }, 54 | } 55 | }; 56 | } 57 | 58 | #[macro_export] 59 | macro_rules! unlikely { 60 | ($e:expr) => { 61 | match $e { 62 | #[allow(unused_unsafe)] 63 | e => unsafe { std::intrinsics::unlikely(e) }, 64 | } 65 | }; 66 | } 67 | 68 | pub mod base_n; 69 | pub mod binary_search_util; 70 | pub mod box_region; 71 | pub mod captures; 72 | pub mod flock; 73 | pub mod functor; 74 | pub mod fx; 75 | pub mod graph; 76 | pub mod jobserver; 77 | pub mod macros; 78 | pub mod map_in_place; 79 | pub mod obligation_forest; 80 | pub mod owning_ref; 81 | pub mod ptr_key; 82 | pub mod sip128; 83 | pub mod small_c_str; 84 | pub mod snapshot_map; 85 | pub mod stable_map; 86 | pub mod svh; 87 | pub use ena::snapshot_vec; 88 | pub mod sorted_map; 89 | pub mod stable_set; 90 | #[macro_use] 91 | pub mod stable_hasher; 92 | mod atomic_ref; 93 | pub mod fingerprint; 94 | pub mod profiling; 95 | pub mod sharded; 96 | pub mod stack; 97 | pub mod sync; 98 | pub mod thin_vec; 99 | pub mod tiny_list; 100 | pub mod transitive_relation; 101 | pub mod vec_linked_list; 102 | pub mod work_queue; 103 | pub use atomic_ref::AtomicRef; 104 | pub mod frozen; 105 | pub mod sso; 106 | pub mod steal; 107 | pub mod tagged_ptr; 108 | pub mod temp_dir; 109 | pub mod unhash; 110 | 111 | pub use ena::undo_log; 112 | pub use ena::unify; 113 | 114 | pub struct OnDrop(pub F); 115 | 116 | impl OnDrop { 117 | /// Forgets the function which prevents it from running. 118 | /// Ensure that the function owns no memory, otherwise it will be leaked. 119 | #[inline] 120 | pub fn disable(self) { 121 | std::mem::forget(self); 122 | } 123 | } 124 | 125 | impl Drop for OnDrop { 126 | #[inline] 127 | fn drop(&mut self) { 128 | (self.0)(); 129 | } 130 | } 131 | 132 | // See comments in src/librustc_middle/lib.rs 133 | #[doc(hidden)] 134 | pub fn __noop_fix_for_27438() {} 135 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/tiny_list/tests.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | extern crate test; 4 | use test::{black_box, Bencher}; 5 | 6 | #[test] 7 | fn test_contains_and_insert() { 8 | fn do_insert(i: u32) -> bool { 9 | i % 2 == 0 10 | } 11 | 12 | let mut list = TinyList::new(); 13 | 14 | for i in 0..10 { 15 | for j in 0..i { 16 | if do_insert(j) { 17 | assert!(list.contains(&j)); 18 | } else { 19 | assert!(!list.contains(&j)); 20 | } 21 | } 22 | 23 | assert!(!list.contains(&i)); 24 | 25 | if do_insert(i) { 26 | list.insert(i); 27 | assert!(list.contains(&i)); 28 | } 29 | } 30 | } 31 | 32 | #[test] 33 | fn test_remove_first() { 34 | let mut list = TinyList::new(); 35 | list.insert(1); 36 | list.insert(2); 37 | list.insert(3); 38 | list.insert(4); 39 | assert_eq!(list.len(), 4); 40 | 41 | assert!(list.remove(&4)); 42 | assert!(!list.contains(&4)); 43 | 44 | assert_eq!(list.len(), 3); 45 | assert!(list.contains(&1)); 46 | assert!(list.contains(&2)); 47 | assert!(list.contains(&3)); 48 | } 49 | 50 | #[test] 51 | fn test_remove_last() { 52 | let mut list = TinyList::new(); 53 | list.insert(1); 54 | list.insert(2); 55 | list.insert(3); 56 | list.insert(4); 57 | assert_eq!(list.len(), 4); 58 | 59 | assert!(list.remove(&1)); 60 | assert!(!list.contains(&1)); 61 | 62 | assert_eq!(list.len(), 3); 63 | assert!(list.contains(&2)); 64 | assert!(list.contains(&3)); 65 | assert!(list.contains(&4)); 66 | } 67 | 68 | #[test] 69 | fn test_remove_middle() { 70 | let mut list = TinyList::new(); 71 | list.insert(1); 72 | list.insert(2); 73 | list.insert(3); 74 | list.insert(4); 75 | assert_eq!(list.len(), 4); 76 | 77 | assert!(list.remove(&2)); 78 | assert!(!list.contains(&2)); 79 | 80 | assert_eq!(list.len(), 3); 81 | assert!(list.contains(&1)); 82 | assert!(list.contains(&3)); 83 | assert!(list.contains(&4)); 84 | } 85 | 86 | #[test] 87 | fn test_remove_single() { 88 | let mut list = TinyList::new(); 89 | list.insert(1); 90 | assert_eq!(list.len(), 1); 91 | 92 | assert!(list.remove(&1)); 93 | assert!(!list.contains(&1)); 94 | 95 | assert_eq!(list.len(), 0); 96 | } 97 | 98 | #[bench] 99 | fn bench_insert_empty(b: &mut Bencher) { 100 | b.iter(|| { 101 | let mut list = black_box(TinyList::new()); 102 | list.insert(1); 103 | list 104 | }) 105 | } 106 | 107 | #[bench] 108 | fn bench_insert_one(b: &mut Bencher) { 109 | b.iter(|| { 110 | let mut list = black_box(TinyList::new_single(0)); 111 | list.insert(1); 112 | list 113 | }) 114 | } 115 | 116 | #[bench] 117 | fn bench_contains_empty(b: &mut Bencher) { 118 | b.iter(|| black_box(TinyList::new()).contains(&1)); 119 | } 120 | 121 | #[bench] 122 | fn bench_contains_unknown(b: &mut Bencher) { 123 | b.iter(|| black_box(TinyList::new_single(0)).contains(&1)); 124 | } 125 | 126 | #[bench] 127 | fn bench_contains_one(b: &mut Bencher) { 128 | b.iter(|| black_box(TinyList::new_single(1)).contains(&1)); 129 | } 130 | 131 | #[bench] 132 | fn bench_remove_empty(b: &mut Bencher) { 133 | b.iter(|| black_box(TinyList::new()).remove(&1)); 134 | } 135 | 136 | #[bench] 137 | fn bench_remove_unknown(b: &mut Bencher) { 138 | b.iter(|| black_box(TinyList::new_single(0)).remove(&1)); 139 | } 140 | 141 | #[bench] 142 | fn bench_remove_one(b: &mut Bencher) { 143 | b.iter(|| black_box(TinyList::new_single(1)).remove(&1)); 144 | } 145 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/map_in_place.rs: -------------------------------------------------------------------------------- 1 | use smallvec::{Array, SmallVec}; 2 | use std::ptr; 3 | 4 | pub trait MapInPlace: Sized { 5 | fn map_in_place(&mut self, mut f: F) 6 | where 7 | F: FnMut(T) -> T, 8 | { 9 | self.flat_map_in_place(|e| Some(f(e))) 10 | } 11 | 12 | fn flat_map_in_place(&mut self, f: F) 13 | where 14 | F: FnMut(T) -> I, 15 | I: IntoIterator; 16 | } 17 | 18 | impl MapInPlace for Vec { 19 | fn flat_map_in_place(&mut self, mut f: F) 20 | where 21 | F: FnMut(T) -> I, 22 | I: IntoIterator, 23 | { 24 | let mut read_i = 0; 25 | let mut write_i = 0; 26 | unsafe { 27 | let mut old_len = self.len(); 28 | self.set_len(0); // make sure we just leak elements in case of panic 29 | 30 | while read_i < old_len { 31 | // move the read_i'th item out of the vector and map it 32 | // to an iterator 33 | let e = ptr::read(self.get_unchecked(read_i)); 34 | let iter = f(e).into_iter(); 35 | read_i += 1; 36 | 37 | for e in iter { 38 | if write_i < read_i { 39 | ptr::write(self.get_unchecked_mut(write_i), e); 40 | write_i += 1; 41 | } else { 42 | // If this is reached we ran out of space 43 | // in the middle of the vector. 44 | // However, the vector is in a valid state here, 45 | // so we just do a somewhat inefficient insert. 46 | self.set_len(old_len); 47 | self.insert(write_i, e); 48 | 49 | old_len = self.len(); 50 | self.set_len(0); 51 | 52 | read_i += 1; 53 | write_i += 1; 54 | } 55 | } 56 | } 57 | 58 | // write_i tracks the number of actually written new items. 59 | self.set_len(write_i); 60 | } 61 | } 62 | } 63 | 64 | impl> MapInPlace for SmallVec { 65 | fn flat_map_in_place(&mut self, mut f: F) 66 | where 67 | F: FnMut(T) -> I, 68 | I: IntoIterator, 69 | { 70 | let mut read_i = 0; 71 | let mut write_i = 0; 72 | unsafe { 73 | let mut old_len = self.len(); 74 | self.set_len(0); // make sure we just leak elements in case of panic 75 | 76 | while read_i < old_len { 77 | // move the read_i'th item out of the vector and map it 78 | // to an iterator 79 | let e = ptr::read(self.get_unchecked(read_i)); 80 | let iter = f(e).into_iter(); 81 | read_i += 1; 82 | 83 | for e in iter { 84 | if write_i < read_i { 85 | ptr::write(self.get_unchecked_mut(write_i), e); 86 | write_i += 1; 87 | } else { 88 | // If this is reached we ran out of space 89 | // in the middle of the vector. 90 | // However, the vector is in a valid state here, 91 | // so we just do a somewhat inefficient insert. 92 | self.set_len(old_len); 93 | self.insert(write_i, e); 94 | 95 | old_len = self.len(); 96 | self.set_len(0); 97 | 98 | read_i += 1; 99 | write_i += 1; 100 | } 101 | } 102 | } 103 | 104 | // write_i tracks the number of actually written new items. 105 | self.set_len(write_i); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /compiler/parser/src/lexer/cursor.rs: -------------------------------------------------------------------------------- 1 | use std::str::Chars; 2 | use tscore_span::{BytePos, Pos}; 3 | 4 | /// Peekable iterator over a char sequence. 5 | /// 6 | /// Next characters can be peeked via `nth_char` method, 7 | /// and position can be shifted forward via `bump` method. 8 | pub(crate) struct Cursor<'a> { 9 | src: &'a str, 10 | chars: Chars<'a>, 11 | #[cfg(debug_assertions)] 12 | prev: char, 13 | 14 | start_pos: BytePos, 15 | pos: BytePos, 16 | end_src_index: usize, 17 | } 18 | 19 | pub(crate) const EOF_CHAR: char = '\0'; 20 | 21 | impl<'a> Cursor<'a> { 22 | pub(crate) fn new(src: &'a str, start_pos: BytePos) -> Cursor<'a> { 23 | Cursor { 24 | src, 25 | chars: src.chars(), 26 | #[cfg(debug_assertions)] 27 | prev: EOF_CHAR, 28 | start_pos, 29 | pos: start_pos, 30 | end_src_index: src.len(), 31 | } 32 | } 33 | 34 | /// Returns the last eaten symbol (or `'\0'` in release builds). 35 | /// (For debug assertions only.) 36 | pub(crate) fn prev(&self) -> char { 37 | #[cfg(debug_assertions)] 38 | { 39 | self.prev 40 | } 41 | 42 | #[cfg(not(debug_assertions))] 43 | { 44 | EOF_CHAR 45 | } 46 | } 47 | 48 | /// Returns nth character relative to the current cursor position. 49 | /// If requested position doesn't exist, `EOF_CHAR` is returned. 50 | /// However, getting `EOF_CHAR` doesn't always mean actual end of file, 51 | /// it should be checked with `is_eof` method. 52 | fn nth_char(&self, n: usize) -> char { 53 | self.chars().nth(n).unwrap_or(EOF_CHAR) 54 | } 55 | 56 | /// Peeks the next symbol from the input stream without consuming it. 57 | pub(crate) fn first(&self) -> char { 58 | self.nth_char(0) 59 | } 60 | 61 | /// Peeks the second symbol from the input stream without consuming it. 62 | pub(crate) fn second(&self) -> char { 63 | self.nth_char(1) 64 | } 65 | 66 | /// Checks if the pos is on start pos 67 | pub(crate) fn is_bof(&self) -> bool { 68 | self.pos == self.start_pos 69 | } 70 | 71 | /// Checks if there is nothing more to consume. 72 | pub(crate) fn is_eof(&self) -> bool { 73 | self.chars.as_str().is_empty() 74 | } 75 | 76 | /// Returns amount of already consumed symbols. 77 | pub(crate) fn len_consumed(&self) -> usize { 78 | self.src.len() - self.chars.as_str().len() 79 | } 80 | 81 | /// Returns a `Chars` iterator over the remaining characters. 82 | fn chars(&self) -> Chars<'a> { 83 | self.chars.clone() 84 | } 85 | 86 | /// Moves to the next character. 87 | pub(crate) fn bump(&mut self) -> Option { 88 | let c = self.chars.next()?; 89 | 90 | #[cfg(debug_assertions)] 91 | { 92 | self.prev = c; 93 | } 94 | 95 | Some(c) 96 | } 97 | 98 | /// Eats symbols while predicate returns true or until the end of file is reached. 99 | pub(crate) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) { 100 | while predicate(self.first()) && !self.is_eof() { 101 | self.bump(); 102 | } 103 | } 104 | 105 | pub(crate) fn cur_pos(&self) -> BytePos { 106 | self.pos 107 | } 108 | 109 | pub(crate) fn text(&self) -> &'a str { 110 | self.chars.as_str() 111 | } 112 | 113 | pub(crate) fn forword_by_usize(&mut self, size: usize) -> BytePos { 114 | self.pos + BytePos::from_usize(size); 115 | 116 | self.pos 117 | } 118 | pub(crate) fn src_index(&self, pos: BytePos) -> usize { 119 | (pos - self.start_pos).to_usize() 120 | } 121 | 122 | /// Slice of the source text from `start` up to but excluding `self.pos`, 123 | /// meaning the slice does not include the character `self.ch`. 124 | pub(crate) fn str_from(&self, start: BytePos) -> &str { 125 | self.str_from_to(start, self.pos) 126 | } 127 | 128 | /// Slice of the source text spanning from `start` up to but excluding `end`. 129 | pub(crate) fn str_from_to(&self, start: BytePos, end: BytePos) -> &str { 130 | &self.src[self.src_index(start)..self.src_index(end)] 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /compiler/span/src/lev_distance.rs: -------------------------------------------------------------------------------- 1 | //! Levenshtein distances. 2 | //! 3 | //! The [Levenshtein distance] is a metric for measuring the difference between two strings. 4 | //! 5 | //! [Levenshtein distance]: https://en.wikipedia.org/wiki/Levenshtein_distance 6 | 7 | use crate::symbol::Symbol; 8 | use std::cmp; 9 | 10 | #[cfg(test)] 11 | mod tests; 12 | 13 | /// Finds the Levenshtein distance between two strings. 14 | pub fn lev_distance(a: &str, b: &str) -> usize { 15 | // cases which don't require further computation 16 | if a.is_empty() { 17 | return b.chars().count(); 18 | } else if b.is_empty() { 19 | return a.chars().count(); 20 | } 21 | 22 | let mut dcol: Vec<_> = (0..=b.len()).collect(); 23 | let mut t_last = 0; 24 | 25 | for (i, sc) in a.chars().enumerate() { 26 | let mut current = i; 27 | dcol[0] = current + 1; 28 | 29 | for (j, tc) in b.chars().enumerate() { 30 | let next = dcol[j + 1]; 31 | if sc == tc { 32 | dcol[j + 1] = current; 33 | } else { 34 | dcol[j + 1] = cmp::min(current, next); 35 | dcol[j + 1] = cmp::min(dcol[j + 1], dcol[j]) + 1; 36 | } 37 | current = next; 38 | t_last = j; 39 | } 40 | } 41 | dcol[t_last + 1] 42 | } 43 | 44 | /// Finds the best match for a given word in the given iterator. 45 | /// 46 | /// As a loose rule to avoid the obviously incorrect suggestions, it takes 47 | /// an optional limit for the maximum allowable edit distance, which defaults 48 | /// to one-third of the given word. 49 | /// 50 | /// Besides Levenshtein, we use case insensitive comparison to improve accuracy 51 | /// on an edge case with a lower(upper)case letters mismatch. 52 | #[cold] 53 | pub fn find_best_match_for_name( 54 | name_vec: &[Symbol], 55 | lookup: Symbol, 56 | dist: Option, 57 | ) -> Option { 58 | let lookup = &lookup.as_str(); 59 | let max_dist = dist.unwrap_or_else(|| cmp::max(lookup.len(), 3) / 3); 60 | 61 | let (case_insensitive_match, levenshtein_match) = name_vec 62 | .iter() 63 | .filter_map(|&name| { 64 | let dist = lev_distance(lookup, &name.as_str()); 65 | if dist <= max_dist { Some((name, dist)) } else { None } 66 | }) 67 | // Here we are collecting the next structure: 68 | // (case_insensitive_match, (levenshtein_match, levenshtein_distance)) 69 | .fold((None, None), |result, (candidate, dist)| { 70 | ( 71 | if candidate.as_str().to_uppercase() == lookup.to_uppercase() { 72 | Some(candidate) 73 | } else { 74 | result.0 75 | }, 76 | match result.1 { 77 | None => Some((candidate, dist)), 78 | Some((c, d)) => Some(if dist < d { (candidate, dist) } else { (c, d) }), 79 | }, 80 | ) 81 | }); 82 | // Priority of matches: 83 | // 1. Exact case insensitive match 84 | // 2. Levenshtein distance match 85 | // 3. Sorted word match 86 | if let Some(candidate) = case_insensitive_match { 87 | Some(candidate) 88 | } else if levenshtein_match.is_some() { 89 | levenshtein_match.map(|(candidate, _)| candidate) 90 | } else { 91 | find_match_by_sorted_words(name_vec, lookup) 92 | } 93 | } 94 | 95 | fn find_match_by_sorted_words(iter_names: &[Symbol], lookup: &str) -> Option { 96 | iter_names.iter().fold(None, |result, candidate| { 97 | if sort_by_words(&candidate.as_str()) == sort_by_words(lookup) { 98 | Some(*candidate) 99 | } else { 100 | result 101 | } 102 | }) 103 | } 104 | 105 | fn sort_by_words(name: &str) -> String { 106 | let mut split_words: Vec<&str> = name.split('_').collect(); 107 | // We are sorting primitive &strs and can use unstable sort here. 108 | split_words.sort_unstable(); 109 | split_words.join("_") 110 | } 111 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/tagged_ptr/drop.rs: -------------------------------------------------------------------------------- 1 | use super::{Pointer, Tag}; 2 | use crate::stable_hasher::{HashStable, StableHasher}; 3 | use std::fmt; 4 | 5 | use super::CopyTaggedPtr; 6 | 7 | /// A TaggedPtr implementing `Drop`. 8 | /// 9 | /// If `COMPARE_PACKED` is true, then the pointers will be compared and hashed without 10 | /// unpacking. Otherwise we don't implement PartialEq/Eq/Hash; if you want that, 11 | /// wrap the TaggedPtr. 12 | pub struct TaggedPtr 13 | where 14 | P: Pointer, 15 | T: Tag, 16 | { 17 | raw: CopyTaggedPtr, 18 | } 19 | 20 | impl Clone for TaggedPtr 21 | where 22 | P: Pointer + Clone, 23 | T: Tag, 24 | { 25 | fn clone(&self) -> Self { 26 | unsafe { Self::new(P::with_ref(self.raw.pointer_raw(), |p| p.clone()), self.raw.tag()) } 27 | } 28 | } 29 | 30 | // We pack the tag into the *upper* bits of the pointer to ease retrieval of the 31 | // value; a right shift is a multiplication and those are embeddable in 32 | // instruction encoding. 33 | impl TaggedPtr 34 | where 35 | P: Pointer, 36 | T: Tag, 37 | { 38 | pub fn new(pointer: P, tag: T) -> Self { 39 | TaggedPtr { raw: CopyTaggedPtr::new(pointer, tag) } 40 | } 41 | 42 | pub fn pointer_ref(&self) -> &P::Target { 43 | self.raw.pointer_ref() 44 | } 45 | pub fn pointer_mut(&mut self) -> &mut P::Target 46 | where 47 | P: std::ops::DerefMut, 48 | { 49 | self.raw.pointer_mut() 50 | } 51 | pub fn tag(&self) -> T { 52 | self.raw.tag() 53 | } 54 | pub fn set_tag(&mut self, tag: T) { 55 | self.raw.set_tag(tag); 56 | } 57 | } 58 | 59 | impl std::ops::Deref for TaggedPtr 60 | where 61 | P: Pointer, 62 | T: Tag, 63 | { 64 | type Target = P::Target; 65 | fn deref(&self) -> &Self::Target { 66 | self.raw.pointer_ref() 67 | } 68 | } 69 | 70 | impl std::ops::DerefMut for TaggedPtr 71 | where 72 | P: Pointer + std::ops::DerefMut, 73 | T: Tag, 74 | { 75 | fn deref_mut(&mut self) -> &mut Self::Target { 76 | self.raw.pointer_mut() 77 | } 78 | } 79 | 80 | impl Drop for TaggedPtr 81 | where 82 | P: Pointer, 83 | T: Tag, 84 | { 85 | fn drop(&mut self) { 86 | // No need to drop the tag, as it's Copy 87 | unsafe { 88 | std::mem::drop(P::from_usize(self.raw.pointer_raw())); 89 | } 90 | } 91 | } 92 | 93 | impl fmt::Debug for TaggedPtr 94 | where 95 | P: Pointer, 96 | P::Target: fmt::Debug, 97 | T: Tag + fmt::Debug, 98 | { 99 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 100 | f.debug_struct("TaggedPtr") 101 | .field("pointer", &self.pointer_ref()) 102 | .field("tag", &self.tag()) 103 | .finish() 104 | } 105 | } 106 | 107 | impl PartialEq for TaggedPtr 108 | where 109 | P: Pointer, 110 | T: Tag, 111 | { 112 | fn eq(&self, other: &Self) -> bool { 113 | self.raw.eq(&other.raw) 114 | } 115 | } 116 | 117 | impl Eq for TaggedPtr 118 | where 119 | P: Pointer, 120 | T: Tag, 121 | { 122 | } 123 | 124 | impl std::hash::Hash for TaggedPtr 125 | where 126 | P: Pointer, 127 | T: Tag, 128 | { 129 | fn hash(&self, state: &mut H) { 130 | self.raw.hash(state); 131 | } 132 | } 133 | 134 | impl HashStable for TaggedPtr 135 | where 136 | P: Pointer + HashStable, 137 | T: Tag + HashStable, 138 | { 139 | fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { 140 | self.raw.hash_stable(hcx, hasher); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/graph/implementation/tests.rs: -------------------------------------------------------------------------------- 1 | use crate::graph::implementation::*; 2 | use std::fmt::Debug; 3 | 4 | type TestGraph = Graph<&'static str, &'static str>; 5 | 6 | fn create_graph() -> TestGraph { 7 | let mut graph = Graph::new(); 8 | 9 | // Create a simple graph 10 | // 11 | // F 12 | // | 13 | // V 14 | // A --> B --> C 15 | // | ^ 16 | // v | 17 | // D --> E 18 | 19 | let a = graph.add_node("A"); 20 | let b = graph.add_node("B"); 21 | let c = graph.add_node("C"); 22 | let d = graph.add_node("D"); 23 | let e = graph.add_node("E"); 24 | let f = graph.add_node("F"); 25 | 26 | graph.add_edge(a, b, "AB"); 27 | graph.add_edge(b, c, "BC"); 28 | graph.add_edge(b, d, "BD"); 29 | graph.add_edge(d, e, "DE"); 30 | graph.add_edge(e, c, "EC"); 31 | graph.add_edge(f, b, "FB"); 32 | 33 | return graph; 34 | } 35 | 36 | #[test] 37 | fn each_node() { 38 | let graph = create_graph(); 39 | let expected = ["A", "B", "C", "D", "E", "F"]; 40 | graph.each_node(|idx, node| { 41 | assert_eq!(&expected[idx.0], graph.node_data(idx)); 42 | assert_eq!(expected[idx.0], node.data); 43 | true 44 | }); 45 | } 46 | 47 | #[test] 48 | fn each_edge() { 49 | let graph = create_graph(); 50 | let expected = ["AB", "BC", "BD", "DE", "EC", "FB"]; 51 | graph.each_edge(|idx, edge| { 52 | assert_eq!(expected[idx.0], edge.data); 53 | true 54 | }); 55 | } 56 | 57 | fn test_adjacent_edges( 58 | graph: &Graph, 59 | start_index: NodeIndex, 60 | start_data: N, 61 | expected_incoming: &[(E, N)], 62 | expected_outgoing: &[(E, N)], 63 | ) { 64 | assert!(graph.node_data(start_index) == &start_data); 65 | 66 | let mut counter = 0; 67 | for (edge_index, edge) in graph.incoming_edges(start_index) { 68 | assert!(counter < expected_incoming.len()); 69 | debug!( 70 | "counter={:?} expected={:?} edge_index={:?} edge={:?}", 71 | counter, expected_incoming[counter], edge_index, edge 72 | ); 73 | match expected_incoming[counter] { 74 | (ref e, ref n) => { 75 | assert!(e == &edge.data); 76 | assert!(n == graph.node_data(edge.source())); 77 | assert!(start_index == edge.target); 78 | } 79 | } 80 | counter += 1; 81 | } 82 | assert_eq!(counter, expected_incoming.len()); 83 | 84 | let mut counter = 0; 85 | for (edge_index, edge) in graph.outgoing_edges(start_index) { 86 | assert!(counter < expected_outgoing.len()); 87 | debug!( 88 | "counter={:?} expected={:?} edge_index={:?} edge={:?}", 89 | counter, expected_outgoing[counter], edge_index, edge 90 | ); 91 | match expected_outgoing[counter] { 92 | (ref e, ref n) => { 93 | assert!(e == &edge.data); 94 | assert!(start_index == edge.source); 95 | assert!(n == graph.node_data(edge.target)); 96 | } 97 | } 98 | counter += 1; 99 | } 100 | assert_eq!(counter, expected_outgoing.len()); 101 | } 102 | 103 | #[test] 104 | fn each_adjacent_from_a() { 105 | let graph = create_graph(); 106 | test_adjacent_edges(&graph, NodeIndex(0), "A", &[], &[("AB", "B")]); 107 | } 108 | 109 | #[test] 110 | fn each_adjacent_from_b() { 111 | let graph = create_graph(); 112 | test_adjacent_edges( 113 | &graph, 114 | NodeIndex(1), 115 | "B", 116 | &[("FB", "F"), ("AB", "A")], 117 | &[("BD", "D"), ("BC", "C")], 118 | ); 119 | } 120 | 121 | #[test] 122 | fn each_adjacent_from_c() { 123 | let graph = create_graph(); 124 | test_adjacent_edges(&graph, NodeIndex(2), "C", &[("EC", "E"), ("BC", "B")], &[]); 125 | } 126 | 127 | #[test] 128 | fn each_adjacent_from_d() { 129 | let graph = create_graph(); 130 | test_adjacent_edges(&graph, NodeIndex(3), "D", &[("BD", "B")], &[("DE", "E")]); 131 | } 132 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/snapshot_map/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::fx::FxHashMap; 2 | use crate::undo_log::{Rollback, Snapshots, UndoLogs, VecLog}; 3 | use std::borrow::{Borrow, BorrowMut}; 4 | use std::hash::Hash; 5 | use std::marker::PhantomData; 6 | use std::ops; 7 | 8 | pub use crate::undo_log::Snapshot; 9 | 10 | #[cfg(test)] 11 | mod tests; 12 | 13 | pub type SnapshotMapStorage = SnapshotMap, ()>; 14 | pub type SnapshotMapRef<'a, K, V, L> = SnapshotMap, &'a mut L>; 15 | 16 | pub struct SnapshotMap, L = VecLog>> { 17 | map: M, 18 | undo_log: L, 19 | _marker: PhantomData<(K, V)>, 20 | } 21 | 22 | // HACK(eddyb) manual impl avoids `Default` bounds on `K` and `V`. 23 | impl Default for SnapshotMap 24 | where 25 | M: Default, 26 | L: Default, 27 | { 28 | fn default() -> Self { 29 | SnapshotMap { map: Default::default(), undo_log: Default::default(), _marker: PhantomData } 30 | } 31 | } 32 | 33 | pub enum UndoLog { 34 | Inserted(K), 35 | Overwrite(K, V), 36 | Purged, 37 | } 38 | 39 | impl SnapshotMap { 40 | #[inline] 41 | pub fn with_log(&mut self, undo_log: L2) -> SnapshotMap { 42 | SnapshotMap { map: &mut self.map, undo_log, _marker: PhantomData } 43 | } 44 | } 45 | 46 | impl SnapshotMap 47 | where 48 | K: Hash + Clone + Eq, 49 | M: BorrowMut> + Borrow>, 50 | L: UndoLogs>, 51 | { 52 | pub fn clear(&mut self) { 53 | self.map.borrow_mut().clear(); 54 | self.undo_log.clear(); 55 | } 56 | 57 | pub fn insert(&mut self, key: K, value: V) -> bool { 58 | match self.map.borrow_mut().insert(key.clone(), value) { 59 | None => { 60 | self.undo_log.push(UndoLog::Inserted(key)); 61 | true 62 | } 63 | Some(old_value) => { 64 | self.undo_log.push(UndoLog::Overwrite(key, old_value)); 65 | false 66 | } 67 | } 68 | } 69 | 70 | pub fn remove(&mut self, key: K) -> bool { 71 | match self.map.borrow_mut().remove(&key) { 72 | Some(old_value) => { 73 | self.undo_log.push(UndoLog::Overwrite(key, old_value)); 74 | true 75 | } 76 | None => false, 77 | } 78 | } 79 | 80 | pub fn get(&self, key: &K) -> Option<&V> { 81 | self.map.borrow().get(key) 82 | } 83 | } 84 | 85 | impl SnapshotMap 86 | where 87 | K: Hash + Clone + Eq, 88 | { 89 | pub fn snapshot(&mut self) -> Snapshot { 90 | self.undo_log.start_snapshot() 91 | } 92 | 93 | pub fn commit(&mut self, snapshot: Snapshot) { 94 | self.undo_log.commit(snapshot) 95 | } 96 | 97 | pub fn rollback_to(&mut self, snapshot: Snapshot) { 98 | let map = &mut self.map; 99 | self.undo_log.rollback_to(|| map, snapshot) 100 | } 101 | } 102 | 103 | impl<'k, K, V, M, L> ops::Index<&'k K> for SnapshotMap 104 | where 105 | K: Hash + Clone + Eq, 106 | M: Borrow>, 107 | { 108 | type Output = V; 109 | fn index(&self, key: &'k K) -> &V { 110 | &self.map.borrow()[key] 111 | } 112 | } 113 | 114 | impl Rollback> for SnapshotMap 115 | where 116 | K: Eq + Hash, 117 | M: Rollback>, 118 | { 119 | fn reverse(&mut self, undo: UndoLog) { 120 | self.map.reverse(undo) 121 | } 122 | } 123 | 124 | impl Rollback> for FxHashMap 125 | where 126 | K: Eq + Hash, 127 | { 128 | fn reverse(&mut self, undo: UndoLog) { 129 | match undo { 130 | UndoLog::Inserted(key) => { 131 | self.remove(&key); 132 | } 133 | 134 | UndoLog::Overwrite(key, old_value) => { 135 | self.insert(key, old_value); 136 | } 137 | 138 | UndoLog::Purged => {} 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /compiler/span/src/analyze_source_file/tests.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | macro_rules! test { 4 | (case: $test_name:ident, 5 | text: $text:expr, 6 | source_file_start_pos: $source_file_start_pos:expr, 7 | lines: $lines:expr, 8 | multi_byte_chars: $multi_byte_chars:expr, 9 | non_narrow_chars: $non_narrow_chars:expr,) => { 10 | #[test] 11 | fn $test_name() { 12 | let (lines, multi_byte_chars, non_narrow_chars) = 13 | analyze_source_file($text, BytePos($source_file_start_pos)); 14 | 15 | let expected_lines: Vec = $lines.into_iter().map(BytePos).collect(); 16 | 17 | assert_eq!(lines, expected_lines); 18 | 19 | let expected_mbcs: Vec = $multi_byte_chars 20 | .into_iter() 21 | .map(|(pos, bytes)| MultiByteChar { pos: BytePos(pos), bytes }) 22 | .collect(); 23 | 24 | assert_eq!(multi_byte_chars, expected_mbcs); 25 | 26 | let expected_nncs: Vec = $non_narrow_chars 27 | .into_iter() 28 | .map(|(pos, width)| NonNarrowChar::new(BytePos(pos), width)) 29 | .collect(); 30 | 31 | assert_eq!(non_narrow_chars, expected_nncs); 32 | } 33 | }; 34 | } 35 | 36 | test!( 37 | case: empty_text, 38 | text: "", 39 | source_file_start_pos: 0, 40 | lines: vec![], 41 | multi_byte_chars: vec![], 42 | non_narrow_chars: vec![], 43 | ); 44 | 45 | test!( 46 | case: newlines_short, 47 | text: "a\nc", 48 | source_file_start_pos: 0, 49 | lines: vec![0, 2], 50 | multi_byte_chars: vec![], 51 | non_narrow_chars: vec![], 52 | ); 53 | 54 | test!( 55 | case: newlines_long, 56 | text: "012345678\nabcdef012345678\na", 57 | source_file_start_pos: 0, 58 | lines: vec![0, 10, 26], 59 | multi_byte_chars: vec![], 60 | non_narrow_chars: vec![], 61 | ); 62 | 63 | test!( 64 | case: newline_and_multi_byte_char_in_same_chunk, 65 | text: "01234β789\nbcdef0123456789abcdef", 66 | source_file_start_pos: 0, 67 | lines: vec![0, 11], 68 | multi_byte_chars: vec![(5, 2)], 69 | non_narrow_chars: vec![], 70 | ); 71 | 72 | test!( 73 | case: newline_and_control_char_in_same_chunk, 74 | text: "01234\u{07}6789\nbcdef0123456789abcdef", 75 | source_file_start_pos: 0, 76 | lines: vec![0, 11], 77 | multi_byte_chars: vec![], 78 | non_narrow_chars: vec![(5, 0)], 79 | ); 80 | 81 | test!( 82 | case: multi_byte_char_short, 83 | text: "aβc", 84 | source_file_start_pos: 0, 85 | lines: vec![0], 86 | multi_byte_chars: vec![(1, 2)], 87 | non_narrow_chars: vec![], 88 | ); 89 | 90 | test!( 91 | case: multi_byte_char_long, 92 | text: "0123456789abcΔf012345β", 93 | source_file_start_pos: 0, 94 | lines: vec![0], 95 | multi_byte_chars: vec![(13, 2), (22, 2)], 96 | non_narrow_chars: vec![], 97 | ); 98 | 99 | test!( 100 | case: multi_byte_char_across_chunk_boundary, 101 | text: "0123456789abcdeΔ123456789abcdef01234", 102 | source_file_start_pos: 0, 103 | lines: vec![0], 104 | multi_byte_chars: vec![(15, 2)], 105 | non_narrow_chars: vec![], 106 | ); 107 | 108 | test!( 109 | case: multi_byte_char_across_chunk_boundary_tail, 110 | text: "0123456789abcdeΔ....", 111 | source_file_start_pos: 0, 112 | lines: vec![0], 113 | multi_byte_chars: vec![(15, 2)], 114 | non_narrow_chars: vec![], 115 | ); 116 | 117 | test!( 118 | case: non_narrow_short, 119 | text: "0\t2", 120 | source_file_start_pos: 0, 121 | lines: vec![0], 122 | multi_byte_chars: vec![], 123 | non_narrow_chars: vec![(1, 4)], 124 | ); 125 | 126 | test!( 127 | case: non_narrow_long, 128 | text: "01\t3456789abcdef01234567\u{07}9", 129 | source_file_start_pos: 0, 130 | lines: vec![0], 131 | multi_byte_chars: vec![], 132 | non_narrow_chars: vec![(2, 4), (24, 0)], 133 | ); 134 | 135 | test!( 136 | case: output_offset_all, 137 | text: "01\t345\n789abcΔf01234567\u{07}9\nbcΔf", 138 | source_file_start_pos: 1000, 139 | lines: vec![0 + 1000, 7 + 1000, 27 + 1000], 140 | multi_byte_chars: vec![(13 + 1000, 2), (29 + 1000, 2)], 141 | non_narrow_chars: vec![(2 + 1000, 4), (24 + 1000, 0)], 142 | ); 143 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/graph/vec_graph/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors}; 2 | use rustc_index::vec::{Idx, IndexVec}; 3 | 4 | #[cfg(test)] 5 | mod tests; 6 | 7 | pub struct VecGraph { 8 | /// Maps from a given node to an index where the set of successors 9 | /// for that node starts. The index indexes into the `edges` 10 | /// vector. To find the range for a given node, we look up the 11 | /// start for that node and then the start for the next node 12 | /// (i.e., with an index 1 higher) and get the range between the 13 | /// two. This vector always has an extra entry so that this works 14 | /// even for the max element. 15 | node_starts: IndexVec, 16 | 17 | edge_targets: Vec, 18 | } 19 | 20 | impl VecGraph { 21 | pub fn new(num_nodes: usize, mut edge_pairs: Vec<(N, N)>) -> Self { 22 | // Sort the edges by the source -- this is important. 23 | edge_pairs.sort(); 24 | 25 | let num_edges = edge_pairs.len(); 26 | 27 | // Store the *target* of each edge into `edge_targets`. 28 | let edge_targets: Vec = edge_pairs.iter().map(|&(_, target)| target).collect(); 29 | 30 | // Create the *edge starts* array. We are iterating over over 31 | // the (sorted) edge pairs. We maintain the invariant that the 32 | // length of the `node_starts` array is enough to store the 33 | // current source node -- so when we see that the source node 34 | // for an edge is greater than the current length, we grow the 35 | // edge-starts array by just enough. 36 | let mut node_starts = IndexVec::with_capacity(num_edges); 37 | for (index, &(source, _)) in edge_pairs.iter().enumerate() { 38 | // If we have a list like `[(0, x), (2, y)]`: 39 | // 40 | // - Start out with `node_starts` of `[]` 41 | // - Iterate to `(0, x)` at index 0: 42 | // - Push one entry because `node_starts.len()` (0) is <= the source (0) 43 | // - Leaving us with `node_starts` of `[0]` 44 | // - Iterate to `(2, y)` at index 1: 45 | // - Push one entry because `node_starts.len()` (1) is <= the source (2) 46 | // - Push one entry because `node_starts.len()` (2) is <= the source (2) 47 | // - Leaving us with `node_starts` of `[0, 1, 1]` 48 | // - Loop terminates 49 | while node_starts.len() <= source.index() { 50 | node_starts.push(index); 51 | } 52 | } 53 | 54 | // Pad out the `node_starts` array so that it has `num_nodes + 55 | // 1` entries. Continuing our example above, if `num_nodes` is 56 | // be `3`, we would push one more index: `[0, 1, 1, 2]`. 57 | // 58 | // Interpretation of that vector: 59 | // 60 | // [0, 1, 1, 2] 61 | // ---- range for N=2 62 | // ---- range for N=1 63 | // ---- range for N=0 64 | while node_starts.len() <= num_nodes { 65 | node_starts.push(edge_targets.len()); 66 | } 67 | 68 | assert_eq!(node_starts.len(), num_nodes + 1); 69 | 70 | Self { node_starts, edge_targets } 71 | } 72 | 73 | /// Gets the successors for `source` as a slice. 74 | pub fn successors(&self, source: N) -> &[N] { 75 | let start_index = self.node_starts[source]; 76 | let end_index = self.node_starts[source.plus(1)]; 77 | &self.edge_targets[start_index..end_index] 78 | } 79 | } 80 | 81 | impl DirectedGraph for VecGraph { 82 | type Node = N; 83 | } 84 | 85 | impl WithNumNodes for VecGraph { 86 | fn num_nodes(&self) -> usize { 87 | self.node_starts.len() - 1 88 | } 89 | } 90 | 91 | impl WithNumEdges for VecGraph { 92 | fn num_edges(&self) -> usize { 93 | self.edge_targets.len() 94 | } 95 | } 96 | 97 | impl GraphSuccessors<'graph> for VecGraph { 98 | type Item = N; 99 | 100 | type Iter = std::iter::Cloned>; 101 | } 102 | 103 | impl WithSuccessors for VecGraph { 104 | fn successors(&self, node: N) -> >::Iter { 105 | self.successors(node).iter().cloned() 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /compiler/ast/src/ast/decl.rs: -------------------------------------------------------------------------------- 1 | use crate::ptr::P; 2 | use crate::token::{self, CommentKind, DelimToken, Token}; 3 | use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream, TokenTree}; 4 | 5 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; 6 | use rustc_data_structures::stack::ensure_sufficient_stack; 7 | use rustc_data_structures::sync::Lrc; 8 | use rustc_data_structures::thin_vec::ThinVec; 9 | use rustc_macros::HashStable_Generic; 10 | use rustc_serialize::{self, Decoder, Encoder}; 11 | use tscore_span::source_map::{respan, Spanned}; 12 | use tscore_span::symbol::{kw, sym, Ident, Symbol}; 13 | use tscore_span::{Span, DUMMY_SP}; 14 | 15 | use super::{ 16 | Class, Expr, Fn, FnSig, Generics, Heritage, JSDoc, NameBinding, Pat, PropName, StrLit, Ty, 17 | }; 18 | 19 | use std::cmp::Ordering; 20 | use std::convert::TryFrom; 21 | use std::fmt; 22 | 23 | #[derive(Clone, Encodable, Decodable, Debug)] 24 | pub enum DeclName { 25 | Ident(Ident), 26 | Lit, 27 | } 28 | #[derive(Clone, Encodable, Decodable, Debug)] 29 | pub enum VarDeclKind { 30 | Var, 31 | Let, 32 | Const, 33 | } 34 | 35 | #[derive(Clone, Encodable, Decodable, Debug)] 36 | pub struct VarDecl { 37 | pub name: Pat, 38 | pub ty: Option, 39 | pub definite: bool, 40 | pub init: Option, 41 | pub span: Span, 42 | } 43 | 44 | #[derive(Clone, Encodable, Decodable, Debug)] 45 | pub struct VarDeclList { 46 | pub kind: VarDeclKind, 47 | pub decls: Vec, 48 | pub span: Span, 49 | pub js_docs: Vec, 50 | } 51 | 52 | #[derive(Clone, Encodable, Decodable, Debug)] 53 | pub struct Decorator { 54 | pub span: Span, 55 | pub expr: P, 56 | } 57 | 58 | #[derive(Clone, Encodable, Decodable, Debug)] 59 | pub enum InterfaceElement { 60 | CallSig(P), 61 | ConstructorSig(P), 62 | PropSig(P, P), 63 | MethodSig(P, P), 64 | IndexSig(P), 65 | } 66 | 67 | #[derive(Clone, Encodable, Decodable, Debug)] 68 | pub struct Interface { 69 | pub name: Ident, 70 | pub generics: Generics, 71 | pub heritages: Vec, 72 | pub elements: Vec, 73 | pub span: Span, 74 | } 75 | 76 | #[derive(Clone, Encodable, Decodable, Debug)] 77 | pub struct TypeAlias { 78 | pub name: Ident, 79 | pub generics: Generics, 80 | pub ty: P, 81 | pub span: Span, 82 | } 83 | 84 | #[derive(Clone, Encodable, Decodable, Debug)] 85 | pub struct Import { 86 | /// Default binding. 87 | /// 88 | /// > Default binding can coexists with one of namespace binding or names binding. 89 | /// 90 | /// `import defaultExport from 'module-name'` 91 | /// 92 | /// Combine with named import: 93 | /// `import defaultExport, { export1 } from 'module-name'` 94 | /// 95 | /// Combine with Namespace imprt: 96 | /// `import defaultExport, * as name from 'module-name'` 97 | pub default: Option, 98 | /// Namespace import binding. 99 | /// 100 | /// `import * as name from 'module-name'` 101 | pub namespcae: Option, 102 | /// `import { export1, export2 as alias2 } from 'module-name'` 103 | pub names: Vec, 104 | pub from: StrLit, 105 | pub type_only: bool, 106 | pub span: Span, 107 | } 108 | 109 | #[derive(Clone, Encodable, Decodable, Debug)] 110 | pub struct Export { 111 | pub type_only: bool, 112 | /// 113 | /// `export * as name from 'module-name'` 114 | /// 115 | pub namespace: Option, 116 | /// 117 | /// `export { a, b as b1 } from 'module-name'` 118 | pub names: Vec, 119 | /// Re-export 120 | /// 121 | /// ```js 122 | /// export { ... } from 'module-name' 123 | /// ``` 124 | pub from: StrLit, 125 | pub span: Span, 126 | } 127 | 128 | #[derive(Clone, Encodable, Decodable, Debug)] 129 | pub enum DeclKind { 130 | /// A variable(s) declaration statement. 131 | /// 132 | /// E.g., `let a = 1`, `let a = 1, b = 2` 133 | /// 134 | /// It could has an preceding jsdoc with some meta data: 135 | /// ```js 136 | /// /** 137 | /// * @type {string} 138 | /// */ 139 | /// let name 140 | /// ``` 141 | Var(P), 142 | Fn(P), 143 | Class(P), 144 | Interface(P), 145 | /// The static import statement is used to import read only live bindings which are exported by another module. 146 | /// 147 | /// See [Import] for more detail. 148 | Import(P), 149 | Export(P), 150 | Type(P), 151 | } 152 | 153 | #[derive(Clone, Encodable, Decodable, Debug)] 154 | pub struct Decl { 155 | pub kind: DeclKind, 156 | pub span: Span, 157 | } 158 | 159 | #[derive(Clone, Encodable, Decodable, Debug)] 160 | pub struct DeclList { 161 | pub span: Span, 162 | pub decls: Vec, 163 | } 164 | -------------------------------------------------------------------------------- /rustc/rustc_serialize/src/json/tests.rs: -------------------------------------------------------------------------------- 1 | // Benchmarks and tests that require private items 2 | 3 | extern crate test; 4 | use super::{from_str, Parser, Stack, StackElement}; 5 | use std::string; 6 | use test::Bencher; 7 | 8 | #[test] 9 | fn test_stack() { 10 | let mut stack = Stack::new(); 11 | 12 | assert!(stack.is_empty()); 13 | assert!(stack.is_empty()); 14 | assert!(!stack.last_is_index()); 15 | 16 | stack.push_index(0); 17 | stack.bump_index(); 18 | 19 | assert!(stack.len() == 1); 20 | assert!(stack.is_equal_to(&[StackElement::Index(1)])); 21 | assert!(stack.starts_with(&[StackElement::Index(1)])); 22 | assert!(stack.ends_with(&[StackElement::Index(1)])); 23 | assert!(stack.last_is_index()); 24 | assert!(stack.get(0) == StackElement::Index(1)); 25 | 26 | stack.push_key("foo".to_string()); 27 | 28 | assert!(stack.len() == 2); 29 | assert!(stack.is_equal_to(&[StackElement::Index(1), StackElement::Key("foo")])); 30 | assert!(stack.starts_with(&[StackElement::Index(1), StackElement::Key("foo")])); 31 | assert!(stack.starts_with(&[StackElement::Index(1)])); 32 | assert!(stack.ends_with(&[StackElement::Index(1), StackElement::Key("foo")])); 33 | assert!(stack.ends_with(&[StackElement::Key("foo")])); 34 | assert!(!stack.last_is_index()); 35 | assert!(stack.get(0) == StackElement::Index(1)); 36 | assert!(stack.get(1) == StackElement::Key("foo")); 37 | 38 | stack.push_key("bar".to_string()); 39 | 40 | assert!(stack.len() == 3); 41 | assert!(stack.is_equal_to(&[ 42 | StackElement::Index(1), 43 | StackElement::Key("foo"), 44 | StackElement::Key("bar") 45 | ])); 46 | assert!(stack.starts_with(&[StackElement::Index(1)])); 47 | assert!(stack.starts_with(&[StackElement::Index(1), StackElement::Key("foo")])); 48 | assert!(stack.starts_with(&[ 49 | StackElement::Index(1), 50 | StackElement::Key("foo"), 51 | StackElement::Key("bar") 52 | ])); 53 | assert!(stack.ends_with(&[StackElement::Key("bar")])); 54 | assert!(stack.ends_with(&[StackElement::Key("foo"), StackElement::Key("bar")])); 55 | assert!(stack.ends_with(&[ 56 | StackElement::Index(1), 57 | StackElement::Key("foo"), 58 | StackElement::Key("bar") 59 | ])); 60 | assert!(!stack.last_is_index()); 61 | assert!(stack.get(0) == StackElement::Index(1)); 62 | assert!(stack.get(1) == StackElement::Key("foo")); 63 | assert!(stack.get(2) == StackElement::Key("bar")); 64 | 65 | stack.pop(); 66 | 67 | assert!(stack.len() == 2); 68 | assert!(stack.is_equal_to(&[StackElement::Index(1), StackElement::Key("foo")])); 69 | assert!(stack.starts_with(&[StackElement::Index(1), StackElement::Key("foo")])); 70 | assert!(stack.starts_with(&[StackElement::Index(1)])); 71 | assert!(stack.ends_with(&[StackElement::Index(1), StackElement::Key("foo")])); 72 | assert!(stack.ends_with(&[StackElement::Key("foo")])); 73 | assert!(!stack.last_is_index()); 74 | assert!(stack.get(0) == StackElement::Index(1)); 75 | assert!(stack.get(1) == StackElement::Key("foo")); 76 | } 77 | 78 | #[bench] 79 | fn bench_streaming_small(b: &mut Bencher) { 80 | b.iter(|| { 81 | let mut parser = Parser::new( 82 | r#"{ 83 | "a": 1.0, 84 | "b": [ 85 | true, 86 | "foo\nbar", 87 | { "c": {"d": null} } 88 | ] 89 | }"# 90 | .chars(), 91 | ); 92 | loop { 93 | match parser.next() { 94 | None => return, 95 | _ => {} 96 | } 97 | } 98 | }); 99 | } 100 | #[bench] 101 | fn bench_small(b: &mut Bencher) { 102 | b.iter(|| { 103 | let _ = from_str( 104 | r#"{ 105 | "a": 1.0, 106 | "b": [ 107 | true, 108 | "foo\nbar", 109 | { "c": {"d": null} } 110 | ] 111 | }"#, 112 | ); 113 | }); 114 | } 115 | 116 | fn big_json() -> string::String { 117 | let mut src = "[\n".to_string(); 118 | for _ in 0..500 { 119 | src.push_str( 120 | r#"{ "a": true, "b": null, "c":3.1415, "d": "Hello world", "e": \ 121 | [1,2,3]},"#, 122 | ); 123 | } 124 | src.push_str("{}]"); 125 | return src; 126 | } 127 | 128 | #[bench] 129 | fn bench_streaming_large(b: &mut Bencher) { 130 | let src = big_json(); 131 | b.iter(|| { 132 | let mut parser = Parser::new(src.chars()); 133 | loop { 134 | match parser.next() { 135 | None => return, 136 | _ => {} 137 | } 138 | } 139 | }); 140 | } 141 | #[bench] 142 | fn bench_large(b: &mut Bencher) { 143 | let src = big_json(); 144 | b.iter(|| { 145 | let _ = from_str(&src); 146 | }); 147 | } 148 | -------------------------------------------------------------------------------- /rustc/rustc_macros/src/hash_stable.rs: -------------------------------------------------------------------------------- 1 | use proc_macro2::{self, Ident}; 2 | use quote::quote; 3 | use syn::{self, parse_quote, Meta, NestedMeta}; 4 | 5 | struct Attributes { 6 | ignore: bool, 7 | project: Option, 8 | } 9 | 10 | fn parse_attributes(field: &syn::Field) -> Attributes { 11 | let mut attrs = Attributes { ignore: false, project: None }; 12 | for attr in &field.attrs { 13 | if let Ok(meta) = attr.parse_meta() { 14 | if !meta.path().is_ident("stable_hasher") { 15 | continue; 16 | } 17 | let mut any_attr = false; 18 | if let Meta::List(list) = meta { 19 | for nested in list.nested.iter() { 20 | if let NestedMeta::Meta(meta) = nested { 21 | if meta.path().is_ident("ignore") { 22 | attrs.ignore = true; 23 | any_attr = true; 24 | } 25 | if meta.path().is_ident("project") { 26 | if let Meta::List(list) = meta { 27 | if let Some(nested) = list.nested.iter().next() { 28 | if let NestedMeta::Meta(meta) = nested { 29 | attrs.project = meta.path().get_ident().cloned(); 30 | any_attr = true; 31 | } 32 | } 33 | } 34 | } 35 | } 36 | } 37 | } 38 | if !any_attr { 39 | panic!("error parsing stable_hasher"); 40 | } 41 | } 42 | } 43 | attrs 44 | } 45 | 46 | pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { 47 | let generic: syn::GenericParam = parse_quote!(__CTX); 48 | s.add_bounds(synstructure::AddBounds::Generics); 49 | s.add_impl_generic(generic); 50 | s.add_where_predicate(parse_quote! { __CTX: crate::HashStableContext }); 51 | let body = s.each(|bi| { 52 | let attrs = parse_attributes(bi.ast()); 53 | if attrs.ignore { 54 | quote! {} 55 | } else if let Some(project) = attrs.project { 56 | quote! { 57 | &#bi.#project.hash_stable(__hcx, __hasher); 58 | } 59 | } else { 60 | quote! { 61 | #bi.hash_stable(__hcx, __hasher); 62 | } 63 | } 64 | }); 65 | 66 | let discriminant = match s.ast().data { 67 | syn::Data::Enum(_) => quote! { 68 | ::std::mem::discriminant(self).hash_stable(__hcx, __hasher); 69 | }, 70 | syn::Data::Struct(_) => quote! {}, 71 | syn::Data::Union(_) => panic!("cannot derive on union"), 72 | }; 73 | 74 | s.bound_impl( 75 | quote!(::rustc_data_structures::stable_hasher::HashStable<__CTX>), 76 | quote! { 77 | fn hash_stable( 78 | &self, 79 | __hcx: &mut __CTX, 80 | __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { 81 | #discriminant 82 | match *self { #body } 83 | } 84 | }, 85 | ) 86 | } 87 | 88 | pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { 89 | let generic: syn::GenericParam = parse_quote!('__ctx); 90 | s.add_bounds(synstructure::AddBounds::Generics); 91 | s.add_impl_generic(generic); 92 | let body = s.each(|bi| { 93 | let attrs = parse_attributes(bi.ast()); 94 | if attrs.ignore { 95 | quote! {} 96 | } else if let Some(project) = attrs.project { 97 | quote! { 98 | &#bi.#project.hash_stable(__hcx, __hasher); 99 | } 100 | } else { 101 | quote! { 102 | #bi.hash_stable(__hcx, __hasher); 103 | } 104 | } 105 | }); 106 | 107 | let discriminant = match s.ast().data { 108 | syn::Data::Enum(_) => quote! { 109 | ::std::mem::discriminant(self).hash_stable(__hcx, __hasher); 110 | }, 111 | syn::Data::Struct(_) => quote! {}, 112 | syn::Data::Union(_) => panic!("cannot derive on union"), 113 | }; 114 | 115 | s.bound_impl( 116 | quote!( 117 | ::rustc_data_structures::stable_hasher::HashStable< 118 | ::rustc_middle::ich::StableHashingContext<'__ctx>, 119 | > 120 | ), 121 | quote! { 122 | fn hash_stable( 123 | &self, 124 | __hcx: &mut ::rustc_middle::ich::StableHashingContext<'__ctx>, 125 | __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { 126 | #discriminant 127 | match *self { #body } 128 | } 129 | }, 130 | ) 131 | } 132 | -------------------------------------------------------------------------------- /compiler/common/src/compiler_options.rs: -------------------------------------------------------------------------------- 1 | use super::types::{ 2 | ImportsNotUsedAsValues, JsxEmit, ModuleKind, ModuleResolutionKind, NewLineKind, ScriptTarget, 3 | TsConfigSourceFile, 4 | }; 5 | use std::collections::HashMap; 6 | 7 | pub struct CompilerOptions { 8 | pub(crate) all: bool, 9 | pub allow_js: bool, 10 | pub(crate) allow_non_ts_extensions: bool, 11 | pub allow_synthetic_default_imports: bool, 12 | pub allow_umd_global_access: bool, 13 | pub allow_unreachable_code: bool, 14 | pub allow_unused_labels: bool, 15 | pub always_strict: bool, // Always combine with strict propert, 16 | pub base_url: Option, 17 | /** An error if set - this should only go through the -b pipeline and not actually be observed */ 18 | pub(crate) build: bool, 19 | pub charset: Option, 20 | pub check_js: bool, 21 | pub(crate) config_file_path: Option, 22 | /** configFile is set as non enumerable property so as to avoid checking of json source files */ 23 | pub(crate) config_file: Option, 24 | pub declaration: bool, 25 | pub declaration_map: bool, 26 | pub emit_declaration_only: bool, 27 | pub declaration_dir: Option, 28 | pub(crate) diagnostics: bool, 29 | pub(crate) extended_diagnostics: bool, 30 | pub disable_size_limit: bool, 31 | pub disable_source_of_project_reference_redirect: bool, 32 | pub disable_solution_searching: bool, 33 | pub disable_referenced_project_load: bool, 34 | pub downlevel_iteration: bool, 35 | pub emit_bom: bool, 36 | pub emit_decorator_metadata: bool, 37 | pub experimental_decorators: bool, 38 | pub force_consistent_casing_in_file_names: bool, 39 | pub(crate) generate_cpu_profile: Option, 40 | pub(crate) help: bool, 41 | pub import_helpers: bool, 42 | pub imports_not_used_as_values: Option, 43 | pub(crate) init: bool, 44 | pub inline_source_map: bool, 45 | pub inline_sources: bool, 46 | pub isolated_modules: bool, 47 | pub jsx: Option, 48 | pub keyof_strings_only: bool, 49 | pub lib: Vec, 50 | pub(crate) list_emitted_files: bool, 51 | pub(crate) list_files: bool, 52 | pub(crate) list_files_only: bool, 53 | pub locale: Option, 54 | pub map_root: Option, 55 | pub max_node_module_js_depth: Option, 56 | pub module: Option, 57 | pub module_resolution: Option, 58 | pub new_line: Option, 59 | pub no_emit: bool, 60 | pub(crate) no_emit_for_js_files: bool, 61 | pub no_emit_helpers: bool, 62 | pub no_emit_on_error: bool, 63 | pub no_error_truncation: bool, 64 | pub no_fallthrough_cases_in_switch: bool, 65 | pub no_implicit_any: bool, // Always combine with strict property 66 | pub no_implicit_returns: bool, 67 | pub no_implicit_this: bool, // Always combine with strict property 68 | pub no_strict_generic_checks: bool, 69 | pub no_unused_locals: bool, 70 | pub no_unused_parameters: bool, 71 | pub no_implicit_use_strict: bool, 72 | pub assume_changes_only_affect_direct_dependencies: bool, 73 | pub no_lib: bool, 74 | pub no_resolve: bool, 75 | pub out: Option, 76 | pub out_dir: Option, 77 | pub out_file: Option, 78 | pub paths: HashMap>, 79 | pub(crate) plugins: Vec, 80 | pub preserve_const_enums: bool, 81 | pub preserve_symlinks: bool, 82 | pub(crate) preserve_watch_output: bool, 83 | pub project: Option, 84 | pub(crate) pretty: bool, 85 | pub react_namespace: Option, 86 | pub jsx_factory: Option, 87 | pub jsx_fragment_factory: Option, 88 | pub composite: bool, 89 | pub incremental: bool, 90 | pub ts_build_info_file: Option, 91 | pub remove_comments: bool, 92 | pub root_dir: Option, 93 | pub root_dirs: Vec, 94 | pub skip_lib_check: bool, 95 | pub skip_default_lib_check: bool, 96 | pub source_map: bool, 97 | pub source_root: Option, 98 | pub strict: bool, 99 | pub strict_function_types: bool, // Always combine with strict property 100 | pub strict_bind_call_apply: bool, // Always combine with strict property 101 | pub strict_null_checks: bool, // Always combine with strict property 102 | pub strict_property_initialization: bool, // Always combine with strict property 103 | pub strip_internal: bool, 104 | pub suppress_excess_property_errors: bool, 105 | pub suppress_implicit_any_index_errors: bool, 106 | pub(crate) suppress_output_path_check: bool, 107 | pub target: Option, // TODO: GH#18217 frequently asserted as defined 108 | pub trace_resolution: bool, 109 | pub resolve_json_module: bool, 110 | pub types: Vec, 111 | /** Paths used to compute primary types search locations */ 112 | pub type_roots: Vec, 113 | pub(crate) version: bool, 114 | pub(crate) watch: bool, 115 | pub es_module_interop: bool, 116 | pub(crate) show_config: bool, 117 | pub use_define_for_class_fields: bool, 118 | } 119 | 120 | impl Default for CompilerOptions { 121 | fn default() -> Self { 122 | Self { allow_js: true, ..Default::default() } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/graph/dominators/mod.rs: -------------------------------------------------------------------------------- 1 | //! Finding the dominators in a control-flow graph. 2 | //! 3 | //! Algorithm based on Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy, 4 | //! "A Simple, Fast Dominance Algorithm", 5 | //! Rice Computer Science TS-06-33870, 6 | //! . 7 | 8 | use super::iterate::reverse_post_order; 9 | use super::ControlFlowGraph; 10 | use rustc_index::vec::{Idx, IndexVec}; 11 | use std::cmp::Ordering; 12 | 13 | #[cfg(test)] 14 | mod tests; 15 | 16 | pub fn dominators(graph: G) -> Dominators { 17 | let start_node = graph.start_node(); 18 | let rpo = reverse_post_order(&graph, start_node); 19 | dominators_given_rpo(graph, &rpo) 20 | } 21 | 22 | fn dominators_given_rpo(graph: G, rpo: &[G::Node]) -> Dominators { 23 | let start_node = graph.start_node(); 24 | assert_eq!(rpo[0], start_node); 25 | 26 | // compute the post order index (rank) for each node 27 | let mut post_order_rank = IndexVec::from_elem_n(0, graph.num_nodes()); 28 | for (index, node) in rpo.iter().rev().cloned().enumerate() { 29 | post_order_rank[node] = index; 30 | } 31 | 32 | let mut immediate_dominators = IndexVec::from_elem_n(None, graph.num_nodes()); 33 | immediate_dominators[start_node] = Some(start_node); 34 | 35 | let mut changed = true; 36 | while changed { 37 | changed = false; 38 | 39 | for &node in &rpo[1..] { 40 | let mut new_idom = None; 41 | for pred in graph.predecessors(node) { 42 | if immediate_dominators[pred].is_some() { 43 | // (*) dominators for `pred` have been calculated 44 | new_idom = Some(if let Some(new_idom) = new_idom { 45 | intersect(&post_order_rank, &immediate_dominators, new_idom, pred) 46 | } else { 47 | pred 48 | }); 49 | } 50 | } 51 | 52 | if new_idom != immediate_dominators[node] { 53 | immediate_dominators[node] = new_idom; 54 | changed = true; 55 | } 56 | } 57 | } 58 | 59 | Dominators { post_order_rank, immediate_dominators } 60 | } 61 | 62 | fn intersect( 63 | post_order_rank: &IndexVec, 64 | immediate_dominators: &IndexVec>, 65 | mut node1: Node, 66 | mut node2: Node, 67 | ) -> Node { 68 | while node1 != node2 { 69 | while post_order_rank[node1] < post_order_rank[node2] { 70 | node1 = immediate_dominators[node1].unwrap(); 71 | } 72 | 73 | while post_order_rank[node2] < post_order_rank[node1] { 74 | node2 = immediate_dominators[node2].unwrap(); 75 | } 76 | } 77 | 78 | node1 79 | } 80 | 81 | #[derive(Clone, Debug)] 82 | pub struct Dominators { 83 | post_order_rank: IndexVec, 84 | immediate_dominators: IndexVec>, 85 | } 86 | 87 | impl Dominators { 88 | pub fn dummy() -> Self { 89 | Self { post_order_rank: IndexVec::new(), immediate_dominators: IndexVec::new() } 90 | } 91 | 92 | pub fn is_reachable(&self, node: Node) -> bool { 93 | self.immediate_dominators[node].is_some() 94 | } 95 | 96 | pub fn immediate_dominator(&self, node: Node) -> Node { 97 | assert!(self.is_reachable(node), "node {:?} is not reachable", node); 98 | self.immediate_dominators[node].unwrap() 99 | } 100 | 101 | pub fn dominators(&self, node: Node) -> Iter<'_, Node> { 102 | assert!(self.is_reachable(node), "node {:?} is not reachable", node); 103 | Iter { dominators: self, node: Some(node) } 104 | } 105 | 106 | pub fn is_dominated_by(&self, node: Node, dom: Node) -> bool { 107 | // FIXME -- could be optimized by using post-order-rank 108 | self.dominators(node).any(|n| n == dom) 109 | } 110 | 111 | /// Provide deterministic ordering of nodes such that, if any two nodes have a dominator 112 | /// relationship, the dominator will always precede the dominated. (The relative ordering 113 | /// of two unrelated nodes will also be consistent, but otherwise the order has no 114 | /// meaning.) This method cannot be used to determine if either Node dominates the other. 115 | pub fn rank_partial_cmp(&self, lhs: Node, rhs: Node) -> Option { 116 | self.post_order_rank[lhs].partial_cmp(&self.post_order_rank[rhs]) 117 | } 118 | } 119 | 120 | pub struct Iter<'dom, Node: Idx> { 121 | dominators: &'dom Dominators, 122 | node: Option, 123 | } 124 | 125 | impl<'dom, Node: Idx> Iterator for Iter<'dom, Node> { 126 | type Item = Node; 127 | 128 | fn next(&mut self) -> Option { 129 | if let Some(node) = self.node { 130 | let dom = self.dominators.immediate_dominator(node); 131 | if dom == node { 132 | self.node = None; // reached the root 133 | } else { 134 | self.node = Some(dom); 135 | } 136 | Some(node) 137 | } else { 138 | None 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /compiler/span/src/span_encoding.rs: -------------------------------------------------------------------------------- 1 | // Spans are encoded using 1-bit tag and 2 different encoding formats (one for each tag value). 2 | // One format is used for keeping span data inline, 3 | // another contains index into an out-of-line span interner. 4 | // The encoding format for inline spans were obtained by optimizing over crates in rustc/libstd. 5 | // See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28 6 | 7 | use crate::SESSION_GLOBALS; 8 | use crate::{BytePos, SpanData}; 9 | 10 | use rustc_data_structures::fx::FxIndexSet; 11 | 12 | /// A compressed span. 13 | /// 14 | /// Whereas [`SpanData`] is 12 bytes, which is a bit too big to stick everywhere, `Span` 15 | /// is a form that only takes up 8 bytes, with less space for the length and 16 | /// context. The vast majority (99.9%+) of `SpanData` instances will fit within 17 | /// those 8 bytes; any `SpanData` whose fields don't fit into a `Span` are 18 | /// stored in a separate interner table, and the `Span` will index into that 19 | /// table. Interning is rare enough that the cost is low, but common enough 20 | /// that the code is exercised regularly. 21 | /// 22 | /// An earlier version of this code used only 4 bytes for `Span`, but that was 23 | /// slower because only 80--90% of spans could be stored inline (even less in 24 | /// very large crates) and so the interner was used a lot more. 25 | /// 26 | /// Inline (compressed) format: 27 | /// - `span.base_or_index == span_data.lo` 28 | /// - `span.len_or_tag == len == span_data.hi - span_data.lo` (must be `<= MAX_LEN`) 29 | /// - `span.ctxt == span_data.ctxt` (must be `<= MAX_CTXT`) 30 | /// 31 | /// Interned format: 32 | /// - `span.base_or_index == index` (indexes into the interner table) 33 | /// - `span.len_or_tag == LEN_TAG` (high bit set, all other bits are zero) 34 | /// - `span.ctxt == 0` 35 | /// 36 | /// The inline form uses 0 for the tag value (rather than 1) so that we don't 37 | /// need to mask out the tag bit when getting the length, and so that the 38 | /// dummy span can be all zeroes. 39 | /// 40 | /// Notes about the choice of field sizes: 41 | /// - `base` is 32 bits in both `Span` and `SpanData`, which means that `base` 42 | /// values never cause interning. The number of bits needed for `base` 43 | /// depends on the crate size. 32 bits allows up to 4 GiB of code in a crate. 44 | /// - `len` is 15 bits in `Span` (a u16, minus 1 bit for the tag) and 32 bits 45 | /// in `SpanData`, which means that large `len` values will cause interning. 46 | /// The number of bits needed for `len` does not depend on the crate size. 47 | /// The most common numbers of bits for `len` are from 0 to 7, with a peak usually 48 | /// at 3 or 4, and then it drops off quickly from 8 onwards. 15 bits is enough 49 | /// for 99.99%+ of cases, but larger values (sometimes 20+ bits) might occur 50 | /// dozens of times in a typical crate. 51 | /// - `ctxt` is 16 bits in `Span` and 32 bits in `SpanData`, which means that 52 | /// large `ctxt` values will cause interning. The number of bits needed for 53 | /// `ctxt` values depend partly on the crate size and partly on the form of 54 | /// the code. No crates in `rustc-perf` need more than 15 bits for `ctxt`, 55 | /// but larger crates might need more than 16 bits. 56 | /// 57 | #[derive(Clone, Copy, Eq, PartialEq, Hash)] 58 | pub struct Span { 59 | base_or_index: u32, 60 | len_or_tag: u16, 61 | } 62 | 63 | const LEN_TAG: u16 = 0b1000_0000_0000_0000; 64 | const MAX_LEN: u32 = 0b0111_1111_1111_1111; 65 | 66 | /// Dummy span, both position and length are zero. 67 | pub const DUMMY_SP: Span = Span { base_or_index: 0, len_or_tag: 0 }; 68 | 69 | impl Span { 70 | #[inline] 71 | pub fn new(mut lo: BytePos, mut hi: BytePos) -> Self { 72 | if lo > hi { 73 | std::mem::swap(&mut lo, &mut hi); 74 | } 75 | 76 | let (base, len) = (lo.0, hi.0 - lo.0); 77 | 78 | if len <= MAX_LEN { 79 | // Inline format. 80 | Span { base_or_index: base, len_or_tag: len as u16 } 81 | } else { 82 | // Interned format. 83 | let index = with_span_interner(|interner| interner.intern(&SpanData { lo, hi })); 84 | Span { base_or_index: index, len_or_tag: LEN_TAG } 85 | } 86 | } 87 | 88 | #[inline] 89 | pub fn data(self) -> SpanData { 90 | if self.len_or_tag != LEN_TAG { 91 | // Inline format. 92 | debug_assert!(self.len_or_tag as u32 <= MAX_LEN); 93 | SpanData { 94 | lo: BytePos(self.base_or_index), 95 | hi: BytePos(self.base_or_index + self.len_or_tag as u32), 96 | } 97 | } else { 98 | // Interned format. 99 | let index = self.base_or_index; 100 | with_span_interner(|interner| *interner.get(index)) 101 | } 102 | } 103 | } 104 | 105 | #[derive(Default)] 106 | pub struct SpanInterner { 107 | spans: FxIndexSet, 108 | } 109 | 110 | impl SpanInterner { 111 | fn intern(&mut self, span_data: &SpanData) -> u32 { 112 | let (index, _) = self.spans.insert_full(*span_data); 113 | index as u32 114 | } 115 | 116 | #[inline] 117 | fn get(&self, index: u32) -> &SpanData { 118 | &self.spans[index as usize] 119 | } 120 | } 121 | 122 | // If an interner exists, return it. Otherwise, prepare a fresh one. 123 | #[inline] 124 | fn with_span_interner T>(f: F) -> T { 125 | SESSION_GLOBALS.with(|session_globals| f(&mut *session_globals.span_interner.lock())) 126 | } 127 | -------------------------------------------------------------------------------- /rustc/rustc_serialize/src/leb128.rs: -------------------------------------------------------------------------------- 1 | #![macro_use] 2 | 3 | macro_rules! max_leb128_len { 4 | ($int_ty:ty) => { 5 | // The longest LEB128 encoding for an integer uses 7 bits per byte. 6 | (std::mem::size_of::<$int_ty>() * 8 + 6) / 7 7 | }; 8 | } 9 | 10 | // Returns the longest LEB128 encoding of all supported integer types. 11 | pub const fn max_leb128_len() -> usize { 12 | max_leb128_len!(u128) 13 | } 14 | 15 | macro_rules! impl_write_unsigned_leb128 { 16 | ($fn_name:ident, $int_ty:ty) => { 17 | #[inline] 18 | pub fn $fn_name( 19 | out: &mut [::std::mem::MaybeUninit; max_leb128_len!($int_ty)], 20 | mut value: $int_ty, 21 | ) -> &[u8] { 22 | let mut i = 0; 23 | 24 | loop { 25 | if value < 0x80 { 26 | unsafe { 27 | *out.get_unchecked_mut(i).as_mut_ptr() = value as u8; 28 | } 29 | 30 | i += 1; 31 | break; 32 | } else { 33 | unsafe { 34 | *out.get_unchecked_mut(i).as_mut_ptr() = ((value & 0x7f) | 0x80) as u8; 35 | } 36 | 37 | value >>= 7; 38 | i += 1; 39 | } 40 | } 41 | 42 | unsafe { ::std::mem::MaybeUninit::slice_assume_init_ref(&out.get_unchecked(..i)) } 43 | } 44 | }; 45 | } 46 | 47 | impl_write_unsigned_leb128!(write_u16_leb128, u16); 48 | impl_write_unsigned_leb128!(write_u32_leb128, u32); 49 | impl_write_unsigned_leb128!(write_u64_leb128, u64); 50 | impl_write_unsigned_leb128!(write_u128_leb128, u128); 51 | impl_write_unsigned_leb128!(write_usize_leb128, usize); 52 | 53 | macro_rules! impl_read_unsigned_leb128 { 54 | ($fn_name:ident, $int_ty:ty) => { 55 | #[inline] 56 | pub fn $fn_name(slice: &[u8]) -> ($int_ty, usize) { 57 | let mut result = 0; 58 | let mut shift = 0; 59 | let mut position = 0; 60 | loop { 61 | let byte = slice[position]; 62 | position += 1; 63 | if (byte & 0x80) == 0 { 64 | result |= (byte as $int_ty) << shift; 65 | return (result, position); 66 | } else { 67 | result |= ((byte & 0x7F) as $int_ty) << shift; 68 | } 69 | shift += 7; 70 | } 71 | } 72 | }; 73 | } 74 | 75 | impl_read_unsigned_leb128!(read_u16_leb128, u16); 76 | impl_read_unsigned_leb128!(read_u32_leb128, u32); 77 | impl_read_unsigned_leb128!(read_u64_leb128, u64); 78 | impl_read_unsigned_leb128!(read_u128_leb128, u128); 79 | impl_read_unsigned_leb128!(read_usize_leb128, usize); 80 | 81 | macro_rules! impl_write_signed_leb128 { 82 | ($fn_name:ident, $int_ty:ty) => { 83 | #[inline] 84 | pub fn $fn_name( 85 | out: &mut [::std::mem::MaybeUninit; max_leb128_len!($int_ty)], 86 | mut value: $int_ty, 87 | ) -> &[u8] { 88 | let mut i = 0; 89 | 90 | loop { 91 | let mut byte = (value as u8) & 0x7f; 92 | value >>= 7; 93 | let more = !(((value == 0) && ((byte & 0x40) == 0)) 94 | || ((value == -1) && ((byte & 0x40) != 0))); 95 | 96 | if more { 97 | byte |= 0x80; // Mark this byte to show that more bytes will follow. 98 | } 99 | 100 | unsafe { 101 | *out.get_unchecked_mut(i).as_mut_ptr() = byte; 102 | } 103 | 104 | i += 1; 105 | 106 | if !more { 107 | break; 108 | } 109 | } 110 | 111 | unsafe { ::std::mem::MaybeUninit::slice_assume_init_ref(&out.get_unchecked(..i)) } 112 | } 113 | }; 114 | } 115 | 116 | impl_write_signed_leb128!(write_i16_leb128, i16); 117 | impl_write_signed_leb128!(write_i32_leb128, i32); 118 | impl_write_signed_leb128!(write_i64_leb128, i64); 119 | impl_write_signed_leb128!(write_i128_leb128, i128); 120 | impl_write_signed_leb128!(write_isize_leb128, isize); 121 | 122 | macro_rules! impl_read_signed_leb128 { 123 | ($fn_name:ident, $int_ty:ty) => { 124 | #[inline] 125 | pub fn $fn_name(slice: &[u8]) -> ($int_ty, usize) { 126 | let mut result = 0; 127 | let mut shift = 0; 128 | let mut position = 0; 129 | let mut byte; 130 | 131 | loop { 132 | byte = slice[position]; 133 | position += 1; 134 | result |= <$int_ty>::from(byte & 0x7F) << shift; 135 | shift += 7; 136 | 137 | if (byte & 0x80) == 0 { 138 | break; 139 | } 140 | } 141 | 142 | if (shift < <$int_ty>::BITS) && ((byte & 0x40) != 0) { 143 | // sign extend 144 | result |= (!0 << shift); 145 | } 146 | 147 | (result, position) 148 | } 149 | }; 150 | } 151 | 152 | impl_read_signed_leb128!(read_i16_leb128, i16); 153 | impl_read_signed_leb128!(read_i32_leb128, i32); 154 | impl_read_signed_leb128!(read_i64_leb128, i64); 155 | impl_read_signed_leb128!(read_i128_leb128, i128); 156 | impl_read_signed_leb128!(read_isize_leb128, isize); 157 | -------------------------------------------------------------------------------- /compiler/ast/src/ast/ty.rs: -------------------------------------------------------------------------------- 1 | use tscore_span::symbol::Ident; 2 | use tscore_span::Span; 3 | 4 | use super::{ExprWithTypeArgs, FnParam, Lit, PropName}; 5 | use crate::ptr::P; 6 | 7 | #[derive(Clone, Encodable, Decodable, Debug)] 8 | pub struct GenericParam { 9 | pub name: Ident, 10 | pub constraint: Option>, 11 | pub defualt: Option>, 12 | } 13 | 14 | #[derive(Clone, Encodable, Decodable, Debug)] 15 | pub struct Generics { 16 | pub span: Span, 17 | pub params: Vec, 18 | } 19 | 20 | #[derive(Clone, Encodable, Decodable, Debug)] 21 | pub struct FnSig { 22 | pub generics: Generics, 23 | pub params: Vec, 24 | pub ret: FnRet, 25 | pub span: Span, 26 | } 27 | 28 | #[derive(Clone, Encodable, Decodable, Debug)] 29 | pub enum FnRet { 30 | Void, 31 | Ty(P), 32 | } 33 | 34 | #[derive(Clone, Encodable, Decodable, Debug)] 35 | pub enum EntityName { 36 | Ident(Ident), 37 | /// ```ts 38 | /// type A = Module.Namespace.A 39 | /// ^^^^^^^^^^^^^^^^ ^ 40 | /// // QualifiedName Ident 41 | /// ``` 42 | Qualified(P, Ident), 43 | } 44 | 45 | #[derive(Clone, Encodable, Decodable, Debug)] 46 | pub enum RefTyKind { 47 | Ident(P, Vec>), 48 | Expr(P), 49 | } 50 | 51 | #[derive(Clone, Encodable, Decodable, Debug)] 52 | pub struct RefTy { 53 | pub span: Span, 54 | pub kind: RefTyKind, 55 | } 56 | 57 | #[derive(Clone, Encodable, Decodable, Debug)] 58 | pub struct CondTy( 59 | /* check */ P, 60 | /* extends */ P, 61 | /* true */ P, 62 | /* false */ P, 63 | ); 64 | 65 | #[derive(Clone, Encodable, Decodable, Debug)] 66 | pub enum OpTyKind { 67 | Keyof, 68 | Readonly, 69 | Uniq, 70 | } 71 | 72 | #[derive(Clone, Encodable, Decodable, Debug)] 73 | pub struct OpTy { 74 | pub kind: OpTyKind, 75 | pub target: P, 76 | pub span: Span, 77 | } 78 | 79 | #[derive(Clone, Encodable, Decodable, Debug)] 80 | pub struct IndexTy(/* object */ P, /* index */ P); 81 | 82 | #[derive(Clone, Encodable, Decodable, Debug)] 83 | pub struct TemplateTySpan { 84 | pub span: Span, 85 | pub ty: P, 86 | pub lit: Option>, 87 | } 88 | 89 | #[derive(Clone, Encodable, Decodable, Debug)] 90 | pub struct TemplateTy { 91 | pub span: Span, 92 | pub head: Option, 93 | pub spans: Vec>, 94 | } 95 | 96 | #[derive(Clone, Encodable, Decodable, Debug)] 97 | pub enum ModFlag { 98 | Raw, 99 | Plus, 100 | Minus, 101 | } 102 | 103 | #[derive(Clone, Encodable, Decodable, Debug)] 104 | pub struct MapTy { 105 | pub readonly_flag: Option, 106 | pub optional_flag: Option, 107 | pub type_params: Generics, 108 | pub optional: bool, 109 | pub ty: Ty, 110 | pub span: Span, 111 | /// TBD 112 | pub name_type: Option, 113 | } 114 | 115 | #[derive(Clone, Encodable, Decodable, Debug)] 116 | pub enum TyKind { 117 | /// ```ts 118 | /// let a: import('module-name').A 119 | /// ``` 120 | Import, 121 | /// ```ts 122 | /// class A { 123 | /// a(a: this) { 124 | /// // ^^^^ 125 | /// } 126 | /// } 127 | /// ``` 128 | This, 129 | Fn(P), 130 | Constructor(P), 131 | /// ```ts 132 | /// type A = Dictionary 133 | /// // ^^^^^^^^^^^^^^^^^^^^^^^^^^ 134 | /// ``` 135 | Ref(P), 136 | /// ```ts 137 | /// let a = 'foo' 138 | /// type A = typeof a 139 | /// // ^^^^^^ 140 | /// ``` 141 | Query(P), 142 | /// ```ts 143 | /// let a: string 144 | /// // ^^^^^^ StringKeyword 145 | /// ``` 146 | Keyword, 147 | /// ```ts 148 | /// let a: string | null 149 | /// // ^^^^ 150 | /// ``` 151 | Lit(P), 152 | /// ```ts 153 | /// let a: { name: string } 154 | /// // ^^^^^^^^^^^^^^^^ 155 | /// ``` 156 | TyLit(Vec>), 157 | /// ```ts 158 | /// let a: A[] 159 | /// ``` 160 | Arr(P), 161 | /// ```ts 162 | /// let a: [number, string] 163 | /// ``` 164 | Tuple(Vec>), 165 | /// ```ts 166 | /// let a: [number, ...string, number] 167 | /// // ^^^^^^^^^ 168 | /// ``` 169 | Rest(P), 170 | /// ```ts 171 | /// 172 | /// let a: [number, ...string, number?] 173 | /// // ^^^^^^^ 174 | /// ``` 175 | Optional(P), 176 | /// ```ts 177 | /// let a: A | B 178 | /// ``` 179 | Union(Vec>), 180 | /// ```ts 181 | /// let a: A & B 182 | /// ``` 183 | Intersection(Vec>), 184 | /// ```ts 185 | /// let a: A extends string ? A : B 186 | /// ``` 187 | Cond(P), 188 | /// ```ts 189 | /// let a: keyof A 190 | /// let a: readonly A 191 | /// let a: unique symbol 192 | /// ``` 193 | Op(P), 194 | /// ```ts 195 | /// let a: (A | B) & C 196 | /// // ^^^^^^^ 197 | /// ``` 198 | Paren(P), 199 | /// ```ts 200 | /// declare function A(): T extends Any ? U : never 201 | /// // ^^^^^^^ 202 | /// ``` 203 | Infer(P), 204 | /// ```ts 205 | /// { [ P in K ] : T } 206 | /// { [ P in K ] ? : T } 207 | /// { -readonly [ P in K ] : T } 208 | /// { readonly [ P in K ] ? : T } 209 | /// ``` 210 | Map(P), 211 | /// ```ts 212 | /// type P1 = Thing["name"]; 213 | /// ``` 214 | Index(P), 215 | /// ```ts 216 | /// type EventName = `${T}Changed`; 217 | /// type T3 = `${'top' | 'bottom'}-${'left' | 'right'}`; 218 | /// ``` 219 | Template(P), 220 | } 221 | 222 | #[derive(Clone, Encodable, Decodable, Debug)] 223 | pub struct Ty { 224 | pub kind: TyKind, 225 | pub name: Option, 226 | pub optional: bool, 227 | pub span: Span, 228 | } 229 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/tagged_ptr/copy.rs: -------------------------------------------------------------------------------- 1 | use super::{Pointer, Tag}; 2 | use crate::stable_hasher::{HashStable, StableHasher}; 3 | use std::fmt; 4 | use std::marker::PhantomData; 5 | use std::num::NonZeroUsize; 6 | 7 | /// A `Copy` TaggedPtr. 8 | /// 9 | /// You should use this instead of the `TaggedPtr` type in all cases where 10 | /// `P: Copy`. 11 | /// 12 | /// If `COMPARE_PACKED` is true, then the pointers will be compared and hashed without 13 | /// unpacking. Otherwise we don't implement PartialEq/Eq/Hash; if you want that, 14 | /// wrap the TaggedPtr. 15 | pub struct CopyTaggedPtr 16 | where 17 | P: Pointer, 18 | T: Tag, 19 | { 20 | packed: NonZeroUsize, 21 | data: PhantomData<(P, T)>, 22 | } 23 | 24 | impl Copy for CopyTaggedPtr 25 | where 26 | P: Pointer, 27 | T: Tag, 28 | P: Copy, 29 | { 30 | } 31 | 32 | impl Clone for CopyTaggedPtr 33 | where 34 | P: Pointer, 35 | T: Tag, 36 | P: Copy, 37 | { 38 | fn clone(&self) -> Self { 39 | *self 40 | } 41 | } 42 | 43 | // We pack the tag into the *upper* bits of the pointer to ease retrieval of the 44 | // value; a left shift is a multiplication and those are embeddable in 45 | // instruction encoding. 46 | impl CopyTaggedPtr 47 | where 48 | P: Pointer, 49 | T: Tag, 50 | { 51 | const TAG_BIT_SHIFT: usize = usize::BITS as usize - T::BITS; 52 | const ASSERTION: () = { 53 | assert!(T::BITS <= P::BITS); 54 | // Used for the transmute_copy's below 55 | assert!(std::mem::size_of::<&P::Target>() == std::mem::size_of::()); 56 | }; 57 | 58 | pub fn new(pointer: P, tag: T) -> Self { 59 | // Trigger assert! 60 | let () = Self::ASSERTION; 61 | let packed_tag = tag.into_usize() << Self::TAG_BIT_SHIFT; 62 | 63 | Self { 64 | // SAFETY: We know that the pointer is non-null, as it must be 65 | // dereferenceable per `Pointer` safety contract. 66 | packed: unsafe { 67 | NonZeroUsize::new_unchecked((P::into_usize(pointer) >> T::BITS) | packed_tag) 68 | }, 69 | data: PhantomData, 70 | } 71 | } 72 | 73 | pub(super) fn pointer_raw(&self) -> usize { 74 | self.packed.get() << T::BITS 75 | } 76 | pub fn pointer(self) -> P 77 | where 78 | P: Copy, 79 | { 80 | // SAFETY: pointer_raw returns the original pointer 81 | // 82 | // Note that this isn't going to double-drop or anything because we have 83 | // P: Copy 84 | unsafe { P::from_usize(self.pointer_raw()) } 85 | } 86 | pub fn pointer_ref(&self) -> &P::Target { 87 | // SAFETY: pointer_raw returns the original pointer 88 | unsafe { std::mem::transmute_copy(&self.pointer_raw()) } 89 | } 90 | pub fn pointer_mut(&mut self) -> &mut P::Target 91 | where 92 | P: std::ops::DerefMut, 93 | { 94 | // SAFETY: pointer_raw returns the original pointer 95 | unsafe { std::mem::transmute_copy(&self.pointer_raw()) } 96 | } 97 | pub fn tag(&self) -> T { 98 | unsafe { T::from_usize(self.packed.get() >> Self::TAG_BIT_SHIFT) } 99 | } 100 | pub fn set_tag(&mut self, tag: T) { 101 | let mut packed = self.packed.get(); 102 | let new_tag = T::into_usize(tag) << Self::TAG_BIT_SHIFT; 103 | let tag_mask = (1 << T::BITS) - 1; 104 | packed &= !(tag_mask << Self::TAG_BIT_SHIFT); 105 | packed |= new_tag; 106 | self.packed = unsafe { NonZeroUsize::new_unchecked(packed) }; 107 | } 108 | } 109 | 110 | impl std::ops::Deref for CopyTaggedPtr 111 | where 112 | P: Pointer, 113 | T: Tag, 114 | { 115 | type Target = P::Target; 116 | fn deref(&self) -> &Self::Target { 117 | self.pointer_ref() 118 | } 119 | } 120 | 121 | impl std::ops::DerefMut for CopyTaggedPtr 122 | where 123 | P: Pointer + std::ops::DerefMut, 124 | T: Tag, 125 | { 126 | fn deref_mut(&mut self) -> &mut Self::Target { 127 | self.pointer_mut() 128 | } 129 | } 130 | 131 | impl fmt::Debug for CopyTaggedPtr 132 | where 133 | P: Pointer, 134 | P::Target: fmt::Debug, 135 | T: Tag + fmt::Debug, 136 | { 137 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 138 | f.debug_struct("CopyTaggedPtr") 139 | .field("pointer", &self.pointer_ref()) 140 | .field("tag", &self.tag()) 141 | .finish() 142 | } 143 | } 144 | 145 | impl PartialEq for CopyTaggedPtr 146 | where 147 | P: Pointer, 148 | T: Tag, 149 | { 150 | fn eq(&self, other: &Self) -> bool { 151 | self.packed == other.packed 152 | } 153 | } 154 | 155 | impl Eq for CopyTaggedPtr 156 | where 157 | P: Pointer, 158 | T: Tag, 159 | { 160 | } 161 | 162 | impl std::hash::Hash for CopyTaggedPtr 163 | where 164 | P: Pointer, 165 | T: Tag, 166 | { 167 | fn hash(&self, state: &mut H) { 168 | self.packed.hash(state); 169 | } 170 | } 171 | 172 | impl HashStable for CopyTaggedPtr 173 | where 174 | P: Pointer + HashStable, 175 | T: Tag + HashStable, 176 | { 177 | fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { 178 | unsafe { 179 | Pointer::with_ref(self.pointer_raw(), |p: &P| p.hash_stable(hcx, hasher)); 180 | } 181 | self.tag().hash_stable(hcx, hasher); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /rustc/rustc_arena/src/tests.rs: -------------------------------------------------------------------------------- 1 | extern crate test; 2 | use super::TypedArena; 3 | use std::cell::Cell; 4 | use test::Bencher; 5 | 6 | #[allow(dead_code)] 7 | #[derive(Debug, Eq, PartialEq)] 8 | struct Point { 9 | x: i32, 10 | y: i32, 11 | z: i32, 12 | } 13 | 14 | #[test] 15 | pub fn test_unused() { 16 | let arena: TypedArena = TypedArena::default(); 17 | assert!(arena.chunks.borrow().is_empty()); 18 | } 19 | 20 | #[test] 21 | fn test_arena_alloc_nested() { 22 | struct Inner { 23 | value: u8, 24 | } 25 | struct Outer<'a> { 26 | inner: &'a Inner, 27 | } 28 | enum EI<'e> { 29 | I(Inner), 30 | O(Outer<'e>), 31 | } 32 | 33 | struct Wrap<'a>(TypedArena>); 34 | 35 | impl<'a> Wrap<'a> { 36 | fn alloc_inner Inner>(&self, f: F) -> &Inner { 37 | let r: &EI<'_> = self.0.alloc(EI::I(f())); 38 | if let &EI::I(ref i) = r { 39 | i 40 | } else { 41 | panic!("mismatch"); 42 | } 43 | } 44 | fn alloc_outer Outer<'a>>(&self, f: F) -> &Outer<'_> { 45 | let r: &EI<'_> = self.0.alloc(EI::O(f())); 46 | if let &EI::O(ref o) = r { 47 | o 48 | } else { 49 | panic!("mismatch"); 50 | } 51 | } 52 | } 53 | 54 | let arena = Wrap(TypedArena::default()); 55 | 56 | let result = arena.alloc_outer(|| Outer { inner: arena.alloc_inner(|| Inner { value: 10 }) }); 57 | 58 | assert_eq!(result.inner.value, 10); 59 | } 60 | 61 | #[test] 62 | pub fn test_copy() { 63 | let arena = TypedArena::default(); 64 | for _ in 0..100000 { 65 | arena.alloc(Point { x: 1, y: 2, z: 3 }); 66 | } 67 | } 68 | 69 | #[bench] 70 | pub fn bench_copy(b: &mut Bencher) { 71 | let arena = TypedArena::default(); 72 | b.iter(|| arena.alloc(Point { x: 1, y: 2, z: 3 })) 73 | } 74 | 75 | #[bench] 76 | pub fn bench_copy_nonarena(b: &mut Bencher) { 77 | b.iter(|| { 78 | let _: Box<_> = Box::new(Point { x: 1, y: 2, z: 3 }); 79 | }) 80 | } 81 | 82 | #[allow(dead_code)] 83 | struct Noncopy { 84 | string: String, 85 | array: Vec, 86 | } 87 | 88 | #[test] 89 | pub fn test_noncopy() { 90 | let arena = TypedArena::default(); 91 | for _ in 0..100000 { 92 | arena.alloc(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] }); 93 | } 94 | } 95 | 96 | #[test] 97 | pub fn test_typed_arena_zero_sized() { 98 | let arena = TypedArena::default(); 99 | for _ in 0..100000 { 100 | arena.alloc(()); 101 | } 102 | } 103 | 104 | #[test] 105 | pub fn test_typed_arena_clear() { 106 | let mut arena = TypedArena::default(); 107 | for _ in 0..10 { 108 | arena.clear(); 109 | for _ in 0..10000 { 110 | arena.alloc(Point { x: 1, y: 2, z: 3 }); 111 | } 112 | } 113 | } 114 | 115 | #[bench] 116 | pub fn bench_typed_arena_clear(b: &mut Bencher) { 117 | let mut arena = TypedArena::default(); 118 | b.iter(|| { 119 | arena.alloc(Point { x: 1, y: 2, z: 3 }); 120 | arena.clear(); 121 | }) 122 | } 123 | 124 | #[bench] 125 | pub fn bench_typed_arena_clear_100(b: &mut Bencher) { 126 | let mut arena = TypedArena::default(); 127 | b.iter(|| { 128 | for _ in 0..100 { 129 | arena.alloc(Point { x: 1, y: 2, z: 3 }); 130 | } 131 | arena.clear(); 132 | }) 133 | } 134 | 135 | // Drop tests 136 | 137 | struct DropCounter<'a> { 138 | count: &'a Cell, 139 | } 140 | 141 | impl Drop for DropCounter<'_> { 142 | fn drop(&mut self) { 143 | self.count.set(self.count.get() + 1); 144 | } 145 | } 146 | 147 | #[test] 148 | fn test_typed_arena_drop_count() { 149 | let counter = Cell::new(0); 150 | { 151 | let arena: TypedArena> = TypedArena::default(); 152 | for _ in 0..100 { 153 | // Allocate something with drop glue to make sure it doesn't leak. 154 | arena.alloc(DropCounter { count: &counter }); 155 | } 156 | }; 157 | assert_eq!(counter.get(), 100); 158 | } 159 | 160 | #[test] 161 | fn test_typed_arena_drop_on_clear() { 162 | let counter = Cell::new(0); 163 | let mut arena: TypedArena> = TypedArena::default(); 164 | for i in 0..10 { 165 | for _ in 0..100 { 166 | // Allocate something with drop glue to make sure it doesn't leak. 167 | arena.alloc(DropCounter { count: &counter }); 168 | } 169 | arena.clear(); 170 | assert_eq!(counter.get(), i * 100 + 100); 171 | } 172 | } 173 | 174 | thread_local! { 175 | static DROP_COUNTER: Cell = Cell::new(0) 176 | } 177 | 178 | struct SmallDroppable; 179 | 180 | impl Drop for SmallDroppable { 181 | fn drop(&mut self) { 182 | DROP_COUNTER.with(|c| c.set(c.get() + 1)); 183 | } 184 | } 185 | 186 | #[test] 187 | fn test_typed_arena_drop_small_count() { 188 | DROP_COUNTER.with(|c| c.set(0)); 189 | { 190 | let arena: TypedArena = TypedArena::default(); 191 | for _ in 0..100 { 192 | // Allocate something with drop glue to make sure it doesn't leak. 193 | arena.alloc(SmallDroppable); 194 | } 195 | // dropping 196 | }; 197 | assert_eq!(DROP_COUNTER.with(|c| c.get()), 100); 198 | } 199 | 200 | #[bench] 201 | pub fn bench_noncopy(b: &mut Bencher) { 202 | let arena = TypedArena::default(); 203 | b.iter(|| { 204 | arena.alloc(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] }) 205 | }) 206 | } 207 | 208 | #[bench] 209 | pub fn bench_noncopy_nonarena(b: &mut Bencher) { 210 | b.iter(|| { 211 | let _: Box<_> = 212 | Box::new(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] }); 213 | }) 214 | } 215 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/tagged_ptr.rs: -------------------------------------------------------------------------------- 1 | //! This module implements tagged pointers. 2 | //! 3 | //! In order to utilize the pointer packing, you must have two types: a pointer, 4 | //! and a tag. 5 | //! 6 | //! The pointer must implement the `Pointer` trait, with the primary requirement 7 | //! being conversion to and from a usize. Note that the pointer must be 8 | //! dereferenceable, so raw pointers generally cannot implement the `Pointer` 9 | //! trait. This implies that the pointer must also be nonzero. 10 | //! 11 | //! Many common pointer types already implement the `Pointer` trait. 12 | //! 13 | //! The tag must implement the `Tag` trait. We assert that the tag and `Pointer` 14 | //! are compatible at compile time. 15 | 16 | use std::mem::ManuallyDrop; 17 | use std::ops::Deref; 18 | use std::rc::Rc; 19 | use std::sync::Arc; 20 | 21 | mod copy; 22 | mod drop; 23 | 24 | pub use copy::CopyTaggedPtr; 25 | pub use drop::TaggedPtr; 26 | 27 | /// This describes the pointer type encapsulated by TaggedPtr. 28 | /// 29 | /// # Safety 30 | /// 31 | /// The usize returned from `into_usize` must be a valid, dereferenceable, 32 | /// pointer to `::Target`. Note that pointers to `Pointee` must 33 | /// be thin, even though `Pointee` may not be sized. 34 | /// 35 | /// Note that the returned pointer from `into_usize` should be castable to `&mut 36 | /// ::Target` if `Pointer: DerefMut`. 37 | /// 38 | /// The BITS constant must be correct. At least `BITS` bits, least-significant, 39 | /// must be zero on all returned pointers from `into_usize`. 40 | /// 41 | /// For example, if the alignment of `Pointee` is 2, then `BITS` should be 1. 42 | pub unsafe trait Pointer: Deref { 43 | /// Most likely the value you want to use here is the following, unless 44 | /// your Pointee type is unsized (e.g., `ty::List` in rustc) in which 45 | /// case you'll need to manually figure out what the right type to pass to 46 | /// align_of is. 47 | /// 48 | /// ```rust 49 | /// std::mem::align_of::<::Target>().trailing_zeros() as usize; 50 | /// ``` 51 | const BITS: usize; 52 | fn into_usize(self) -> usize; 53 | 54 | /// # Safety 55 | /// 56 | /// The passed `ptr` must be returned from `into_usize`. 57 | /// 58 | /// This acts as `ptr::read` semantically, it should not be called more than 59 | /// once on non-`Copy` `Pointer`s. 60 | unsafe fn from_usize(ptr: usize) -> Self; 61 | 62 | /// This provides a reference to the `Pointer` itself, rather than the 63 | /// `Deref::Target`. It is used for cases where we want to call methods that 64 | /// may be implement differently for the Pointer than the Pointee (e.g., 65 | /// `Rc::clone` vs cloning the inner value). 66 | /// 67 | /// # Safety 68 | /// 69 | /// The passed `ptr` must be returned from `into_usize`. 70 | unsafe fn with_ref R>(ptr: usize, f: F) -> R; 71 | } 72 | 73 | /// This describes tags that the `TaggedPtr` struct can hold. 74 | /// 75 | /// # Safety 76 | /// 77 | /// The BITS constant must be correct. 78 | /// 79 | /// No more than `BITS` least significant bits may be set in the returned usize. 80 | pub unsafe trait Tag: Copy { 81 | const BITS: usize; 82 | 83 | fn into_usize(self) -> usize; 84 | 85 | /// # Safety 86 | /// 87 | /// The passed `tag` must be returned from `into_usize`. 88 | unsafe fn from_usize(tag: usize) -> Self; 89 | } 90 | 91 | unsafe impl Pointer for Box { 92 | const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; 93 | fn into_usize(self) -> usize { 94 | Box::into_raw(self) as usize 95 | } 96 | unsafe fn from_usize(ptr: usize) -> Self { 97 | Box::from_raw(ptr as *mut T) 98 | } 99 | unsafe fn with_ref R>(ptr: usize, f: F) -> R { 100 | let raw = ManuallyDrop::new(Self::from_usize(ptr)); 101 | f(&raw) 102 | } 103 | } 104 | 105 | unsafe impl Pointer for Rc { 106 | const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; 107 | fn into_usize(self) -> usize { 108 | Rc::into_raw(self) as usize 109 | } 110 | unsafe fn from_usize(ptr: usize) -> Self { 111 | Rc::from_raw(ptr as *const T) 112 | } 113 | unsafe fn with_ref R>(ptr: usize, f: F) -> R { 114 | let raw = ManuallyDrop::new(Self::from_usize(ptr)); 115 | f(&raw) 116 | } 117 | } 118 | 119 | unsafe impl Pointer for Arc { 120 | const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; 121 | fn into_usize(self) -> usize { 122 | Arc::into_raw(self) as usize 123 | } 124 | unsafe fn from_usize(ptr: usize) -> Self { 125 | Arc::from_raw(ptr as *const T) 126 | } 127 | unsafe fn with_ref R>(ptr: usize, f: F) -> R { 128 | let raw = ManuallyDrop::new(Self::from_usize(ptr)); 129 | f(&raw) 130 | } 131 | } 132 | 133 | unsafe impl<'a, T: 'a> Pointer for &'a T { 134 | const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; 135 | fn into_usize(self) -> usize { 136 | self as *const T as usize 137 | } 138 | unsafe fn from_usize(ptr: usize) -> Self { 139 | &*(ptr as *const T) 140 | } 141 | unsafe fn with_ref R>(ptr: usize, f: F) -> R { 142 | f(&*(&ptr as *const usize as *const Self)) 143 | } 144 | } 145 | 146 | unsafe impl<'a, T: 'a> Pointer for &'a mut T { 147 | const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; 148 | fn into_usize(self) -> usize { 149 | self as *mut T as usize 150 | } 151 | unsafe fn from_usize(ptr: usize) -> Self { 152 | &mut *(ptr as *mut T) 153 | } 154 | unsafe fn with_ref R>(ptr: usize, f: F) -> R { 155 | f(&*(&ptr as *const usize as *const Self)) 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /rustc/rustc_data_structures/src/sharded.rs: -------------------------------------------------------------------------------- 1 | use crate::fx::{FxHashMap, FxHasher}; 2 | use crate::sync::{Lock, LockGuard}; 3 | use smallvec::SmallVec; 4 | use std::borrow::Borrow; 5 | use std::collections::hash_map::RawEntryMut; 6 | use std::hash::{Hash, Hasher}; 7 | use std::mem; 8 | 9 | #[derive(Clone, Default)] 10 | #[cfg_attr(parallel_compiler, repr(align(64)))] 11 | struct CacheAligned(T); 12 | 13 | #[cfg(parallel_compiler)] 14 | // 32 shards is sufficient to reduce contention on an 8-core Ryzen 7 1700, 15 | // but this should be tested on higher core count CPUs. How the `Sharded` type gets used 16 | // may also affect the ideal number of shards. 17 | const SHARD_BITS: usize = 5; 18 | 19 | #[cfg(not(parallel_compiler))] 20 | const SHARD_BITS: usize = 0; 21 | 22 | pub const SHARDS: usize = 1 << SHARD_BITS; 23 | 24 | /// An array of cache-line aligned inner locked structures with convenience methods. 25 | #[derive(Clone)] 26 | pub struct Sharded { 27 | shards: [CacheAligned>; SHARDS], 28 | } 29 | 30 | impl Default for Sharded { 31 | #[inline] 32 | fn default() -> Self { 33 | Self::new(T::default) 34 | } 35 | } 36 | 37 | impl Sharded { 38 | #[inline] 39 | pub fn new(mut value: impl FnMut() -> T) -> Self { 40 | // Create a vector of the values we want 41 | let mut values: SmallVec<[_; SHARDS]> = 42 | (0..SHARDS).map(|_| CacheAligned(Lock::new(value()))).collect(); 43 | 44 | // Create an uninitialized array 45 | let mut shards: mem::MaybeUninit<[CacheAligned>; SHARDS]> = 46 | mem::MaybeUninit::uninit(); 47 | 48 | unsafe { 49 | // Copy the values into our array 50 | let first = shards.as_mut_ptr() as *mut CacheAligned>; 51 | values.as_ptr().copy_to_nonoverlapping(first, SHARDS); 52 | 53 | // Ignore the content of the vector 54 | values.set_len(0); 55 | 56 | Sharded { shards: shards.assume_init() } 57 | } 58 | } 59 | 60 | /// The shard is selected by hashing `val` with `FxHasher`. 61 | #[inline] 62 | pub fn get_shard_by_value(&self, val: &K) -> &Lock { 63 | if SHARDS == 1 { &self.shards[0].0 } else { self.get_shard_by_hash(make_hash(val)) } 64 | } 65 | 66 | #[inline] 67 | pub fn get_shard_by_hash(&self, hash: u64) -> &Lock { 68 | &self.shards[get_shard_index_by_hash(hash)].0 69 | } 70 | 71 | #[inline] 72 | pub fn get_shard_by_index(&self, i: usize) -> &Lock { 73 | &self.shards[i].0 74 | } 75 | 76 | pub fn lock_shards(&self) -> Vec> { 77 | (0..SHARDS).map(|i| self.shards[i].0.lock()).collect() 78 | } 79 | 80 | pub fn try_lock_shards(&self) -> Option>> { 81 | (0..SHARDS).map(|i| self.shards[i].0.try_lock()).collect() 82 | } 83 | } 84 | 85 | pub type ShardedHashMap = Sharded>; 86 | 87 | impl ShardedHashMap { 88 | pub fn len(&self) -> usize { 89 | self.lock_shards().iter().map(|shard| shard.len()).sum() 90 | } 91 | } 92 | 93 | impl ShardedHashMap { 94 | #[inline] 95 | pub fn intern_ref(&self, value: &Q, make: impl FnOnce() -> K) -> K 96 | where 97 | K: Borrow, 98 | Q: Hash + Eq, 99 | { 100 | let hash = make_hash(value); 101 | let mut shard = self.get_shard_by_hash(hash).lock(); 102 | let entry = shard.raw_entry_mut().from_key_hashed_nocheck(hash, value); 103 | 104 | match entry { 105 | RawEntryMut::Occupied(e) => *e.key(), 106 | RawEntryMut::Vacant(e) => { 107 | let v = make(); 108 | e.insert_hashed_nocheck(hash, v, ()); 109 | v 110 | } 111 | } 112 | } 113 | 114 | #[inline] 115 | pub fn intern(&self, value: Q, make: impl FnOnce(Q) -> K) -> K 116 | where 117 | K: Borrow, 118 | Q: Hash + Eq, 119 | { 120 | let hash = make_hash(&value); 121 | let mut shard = self.get_shard_by_hash(hash).lock(); 122 | let entry = shard.raw_entry_mut().from_key_hashed_nocheck(hash, &value); 123 | 124 | match entry { 125 | RawEntryMut::Occupied(e) => *e.key(), 126 | RawEntryMut::Vacant(e) => { 127 | let v = make(value); 128 | e.insert_hashed_nocheck(hash, v, ()); 129 | v 130 | } 131 | } 132 | } 133 | } 134 | 135 | pub trait IntoPointer { 136 | /// Returns a pointer which outlives `self`. 137 | fn into_pointer(&self) -> *const (); 138 | } 139 | 140 | impl ShardedHashMap { 141 | pub fn contains_pointer_to(&self, value: &T) -> bool { 142 | let hash = make_hash(&value); 143 | let shard = self.get_shard_by_hash(hash).lock(); 144 | let value = value.into_pointer(); 145 | shard.raw_entry().from_hash(hash, |entry| entry.into_pointer() == value).is_some() 146 | } 147 | } 148 | 149 | #[inline] 150 | fn make_hash(val: &K) -> u64 { 151 | let mut state = FxHasher::default(); 152 | val.hash(&mut state); 153 | state.finish() 154 | } 155 | 156 | /// Get a shard with a pre-computed hash value. If `get_shard_by_value` is 157 | /// ever used in combination with `get_shard_by_hash` on a single `Sharded` 158 | /// instance, then `hash` must be computed with `FxHasher`. Otherwise, 159 | /// `hash` can be computed with any hasher, so long as that hasher is used 160 | /// consistently for each `Sharded` instance. 161 | #[inline] 162 | pub fn get_shard_index_by_hash(hash: u64) -> usize { 163 | let hash_len = mem::size_of::(); 164 | // Ignore the top 7 bits as hashbrown uses these and get the next SHARD_BITS highest bits. 165 | // hashbrown also uses the lowest bits, so we can't use those 166 | let bits = (hash >> (hash_len * 8 - 7 - SHARD_BITS)) as usize; 167 | bits % SHARDS 168 | } 169 | -------------------------------------------------------------------------------- /compiler/ast/src/ast/stmt.rs: -------------------------------------------------------------------------------- 1 | use crate::ptr::P; 2 | use crate::token::{self, CommentKind, DelimToken, Token}; 3 | use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream, TokenTree}; 4 | 5 | use super::{Decl, DeclList, Expr, Pat, StrLit, VarDeclList}; 6 | 7 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; 8 | use rustc_data_structures::stack::ensure_sufficient_stack; 9 | use rustc_data_structures::sync::Lrc; 10 | use rustc_data_structures::thin_vec::ThinVec; 11 | use rustc_macros::HashStable_Generic; 12 | use rustc_serialize::{self, Decoder, Encoder}; 13 | use tscore_span::source_map::{respan, Spanned}; 14 | use tscore_span::symbol::{kw, sym, Ident, Symbol}; 15 | use tscore_span::{Span, DUMMY_SP}; 16 | 17 | use std::cmp::Ordering; 18 | use std::convert::TryFrom; 19 | use std::fmt; 20 | 21 | #[derive(Clone, Encodable, Decodable, Debug)] 22 | pub struct Block { 23 | pub stmts: Vec, 24 | pub span: Span, 25 | pub multi_line: Option, 26 | } 27 | 28 | #[derive(Clone, Encodable, Decodable, Debug)] 29 | pub enum ForVal { 30 | Expr(P), 31 | Decl(P), 32 | } 33 | 34 | #[derive(Clone, Encodable, Decodable, Debug)] 35 | pub struct ForCond { 36 | pub init: Option>, 37 | pub test: Option>, 38 | pub update: Option>, 39 | } 40 | 41 | #[derive(Clone, Encodable, Decodable, Debug)] 42 | pub enum IterCondKind { 43 | Do(P), 44 | For(P), 45 | ForInOf(P, P, /* awaitness */ bool), 46 | While(P), 47 | } 48 | 49 | #[derive(Clone, Encodable, Decodable, Debug)] 50 | pub struct IterCond { 51 | pub kind: IterCondKind, 52 | pub stmts: Vec, 53 | pub span: Span, 54 | } 55 | 56 | #[derive(Clone, Encodable, Decodable, Debug)] 57 | pub struct Label(Ident); 58 | 59 | #[derive(Clone, Encodable, Decodable, Debug)] 60 | pub enum SwitchBranch { 61 | Case(P, Vec), 62 | Default(Vec), 63 | } 64 | 65 | #[derive(Clone, Encodable, Decodable, Debug)] 66 | pub struct CatchBlock { 67 | decl: Option, 68 | block: Block, 69 | } 70 | 71 | #[derive(Clone, Encodable, Decodable, Debug)] 72 | pub enum StmtKind { 73 | NotEmitted, 74 | EndOfDeclMark, 75 | MergeDeclMark, 76 | /// An empty statement is used to provide no statement, 77 | /// although the JavaScript syntax would expect one. 78 | Empty, 79 | /// The `debugger` statement invokes any available debugging functionality, such as setting a breakpoint. 80 | /// If no debugging functionality is available, this statement has no effect. 81 | Debugger, 82 | /// The `block` statement (or compound statement in other languages) is used to group zero or more `statements`. 83 | /// 84 | /// E.g., `{ .. }` as in `function foo() { .. }`. 85 | Block(P), 86 | /// The `if` statement executes a statement if a specified `expression` returns truthy. 87 | /// Otherwise, another optional statement can be executed. 88 | /// 89 | /// `if (expr) { block } else { block }` 90 | If(P, P, Option>), 91 | /// General iteration statement. 92 | /// 93 | /// See [IterCond] for more detail. 94 | Iter(P, P), 95 | /// The `break` statement terminates the current loop, switch, or label statement 96 | /// and transfers program control to the statement following the terminated statement. 97 | Break(Option