aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_expand/src
diff options
context:
space:
mode:
authorSeivan Heidari <[email protected]>2019-10-31 08:43:20 +0000
committerSeivan Heidari <[email protected]>2019-10-31 08:43:20 +0000
commit8edda0e7b164009d6c03bb3d4be603fb38ad2e2a (patch)
tree744cf81075d394e2f9c06afb07642a2601800dda /crates/ra_hir_expand/src
parent49562d36b97ddde34cf7585a8c2e8f232519b657 (diff)
parentd067afb064a7fa67b172abf561b7d80740cd6f18 (diff)
Merge branch 'master' into feature/themes
Diffstat (limited to 'crates/ra_hir_expand/src')
-rw-r--r--crates/ra_hir_expand/src/ast_id_map.rs106
-rw-r--r--crates/ra_hir_expand/src/db.rs104
-rw-r--r--crates/ra_hir_expand/src/either.rs54
-rw-r--r--crates/ra_hir_expand/src/hygiene.rs46
-rw-r--r--crates/ra_hir_expand/src/lib.rs153
-rw-r--r--crates/ra_hir_expand/src/name.rs142
6 files changed, 605 insertions, 0 deletions
diff --git a/crates/ra_hir_expand/src/ast_id_map.rs b/crates/ra_hir_expand/src/ast_id_map.rs
new file mode 100644
index 000000000..cb464c3ff
--- /dev/null
+++ b/crates/ra_hir_expand/src/ast_id_map.rs
@@ -0,0 +1,106 @@
1//! `AstIdMap` allows to create stable IDs for "large" syntax nodes like items
2//! and macro calls.
3//!
4//! Specifically, it enumerates all items in a file and uses position of a an
5//! item as an ID. That way, id's don't change unless the set of items itself
6//! changes.
7
8use std::{
9 hash::{Hash, Hasher},
10 marker::PhantomData,
11};
12
13use ra_arena::{impl_arena_id, Arena, RawId};
14use ra_syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr};
15
16/// `AstId` points to an AST node in a specific file.
17#[derive(Debug)]
18pub struct FileAstId<N: AstNode> {
19 raw: ErasedFileAstId,
20 _ty: PhantomData<fn() -> N>,
21}
22
23impl<N: AstNode> Clone for FileAstId<N> {
24 fn clone(&self) -> FileAstId<N> {
25 *self
26 }
27}
28impl<N: AstNode> Copy for FileAstId<N> {}
29
30impl<N: AstNode> PartialEq for FileAstId<N> {
31 fn eq(&self, other: &Self) -> bool {
32 self.raw == other.raw
33 }
34}
35impl<N: AstNode> Eq for FileAstId<N> {}
36impl<N: AstNode> Hash for FileAstId<N> {
37 fn hash<H: Hasher>(&self, hasher: &mut H) {
38 self.raw.hash(hasher);
39 }
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
43struct ErasedFileAstId(RawId);
44impl_arena_id!(ErasedFileAstId);
45
46/// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back.
47#[derive(Debug, PartialEq, Eq, Default)]
48pub struct AstIdMap {
49 arena: Arena<ErasedFileAstId, SyntaxNodePtr>,
50}
51
52impl AstIdMap {
53 pub(crate) fn from_source(node: &SyntaxNode) -> AstIdMap {
54 assert!(node.parent().is_none());
55 let mut res = AstIdMap { arena: Arena::default() };
56 // By walking the tree in bread-first order we make sure that parents
57 // get lower ids then children. That is, adding a new child does not
58 // change parent's id. This means that, say, adding a new function to a
59 // trait does not change ids of top-level items, which helps caching.
60 bfs(node, |it| {
61 if let Some(module_item) = ast::ModuleItem::cast(it.clone()) {
62 res.alloc(module_item.syntax());
63 } else if let Some(macro_call) = ast::MacroCall::cast(it) {
64 res.alloc(macro_call.syntax());
65 }
66 });
67 res
68 }
69
70 pub fn ast_id<N: AstNode>(&self, item: &N) -> FileAstId<N> {
71 let raw = self.erased_ast_id(item.syntax());
72 FileAstId { raw, _ty: PhantomData }
73 }
74 fn erased_ast_id(&self, item: &SyntaxNode) -> ErasedFileAstId {
75 let ptr = SyntaxNodePtr::new(item);
76 match self.arena.iter().find(|(_id, i)| **i == ptr) {
77 Some((it, _)) => it,
78 None => panic!(
79 "Can't find {:?} in AstIdMap:\n{:?}",
80 item,
81 self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),
82 ),
83 }
84 }
85
86 pub(crate) fn get<N: AstNode>(&self, id: FileAstId<N>) -> AstPtr<N> {
87 self.arena[id.raw].cast::<N>().unwrap()
88 }
89
90 fn alloc(&mut self, item: &SyntaxNode) -> ErasedFileAstId {
91 self.arena.alloc(SyntaxNodePtr::new(item))
92 }
93}
94
95/// Walks the subtree in bfs order, calling `f` for each node.
96fn bfs(node: &SyntaxNode, mut f: impl FnMut(SyntaxNode)) {
97 let mut curr_layer = vec![node.clone()];
98 let mut next_layer = vec![];
99 while !curr_layer.is_empty() {
100 curr_layer.drain(..).for_each(|node| {
101 next_layer.extend(node.children());
102 f(node);
103 });
104 std::mem::swap(&mut curr_layer, &mut next_layer);
105 }
106}
diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs
new file mode 100644
index 000000000..a4ee9a529
--- /dev/null
+++ b/crates/ra_hir_expand/src/db.rs
@@ -0,0 +1,104 @@
1//! Defines database & queries for macro expansion.
2
3use std::sync::Arc;
4
5use mbe::MacroRules;
6use ra_db::{salsa, SourceDatabase};
7use ra_prof::profile;
8use ra_syntax::{AstNode, Parse, SyntaxNode};
9
10use crate::{
11 ast_id_map::AstIdMap, HirFileId, HirFileIdRepr, MacroCallId, MacroCallLoc, MacroDefId,
12 MacroFile, MacroFileKind,
13};
14
15// FIXME: rename to ExpandDatabase
16#[salsa::query_group(AstDatabaseStorage)]
17pub trait AstDatabase: SourceDatabase {
18 fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
19
20 #[salsa::transparent]
21 fn parse_or_expand(&self, file_id: HirFileId) -> Option<SyntaxNode>;
22
23 #[salsa::interned]
24 fn intern_macro(&self, macro_call: MacroCallLoc) -> MacroCallId;
25 fn macro_arg(&self, id: MacroCallId) -> Option<Arc<tt::Subtree>>;
26 fn macro_def(&self, id: MacroDefId) -> Option<Arc<mbe::MacroRules>>;
27 fn parse_macro(&self, macro_file: MacroFile) -> Option<Parse<SyntaxNode>>;
28 fn macro_expand(&self, macro_call: MacroCallId) -> Result<Arc<tt::Subtree>, String>;
29}
30
31pub(crate) fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> {
32 let map =
33 db.parse_or_expand(file_id).map_or_else(AstIdMap::default, |it| AstIdMap::from_source(&it));
34 Arc::new(map)
35}
36
37pub(crate) fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<MacroRules>> {
38 let macro_call = id.ast_id.to_node(db);
39 let arg = macro_call.token_tree()?;
40 let (tt, _) = mbe::ast_to_token_tree(&arg).or_else(|| {
41 log::warn!("fail on macro_def to token tree: {:#?}", arg);
42 None
43 })?;
44 let rules = MacroRules::parse(&tt).ok().or_else(|| {
45 log::warn!("fail on macro_def parse: {:#?}", tt);
46 None
47 })?;
48 Some(Arc::new(rules))
49}
50
51pub(crate) fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<tt::Subtree>> {
52 let loc = db.lookup_intern_macro(id);
53 let macro_call = loc.ast_id.to_node(db);
54 let arg = macro_call.token_tree()?;
55 let (tt, _) = mbe::ast_to_token_tree(&arg)?;
56 Some(Arc::new(tt))
57}
58
59pub(crate) fn macro_expand(
60 db: &dyn AstDatabase,
61 id: MacroCallId,
62) -> Result<Arc<tt::Subtree>, String> {
63 let loc = db.lookup_intern_macro(id);
64 let macro_arg = db.macro_arg(id).ok_or("Fail to args in to tt::TokenTree")?;
65
66 let macro_rules = db.macro_def(loc.def).ok_or("Fail to find macro definition")?;
67 let tt = macro_rules.expand(&macro_arg).map_err(|err| format!("{:?}", err))?;
68 // Set a hard limit for the expanded tt
69 let count = tt.count();
70 if count > 65536 {
71 return Err(format!("Total tokens count exceed limit : count = {}", count));
72 }
73 Ok(Arc::new(tt))
74}
75
76pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> {
77 match file_id.0 {
78 HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()),
79 HirFileIdRepr::MacroFile(macro_file) => {
80 db.parse_macro(macro_file).map(|it| it.syntax_node())
81 }
82 }
83}
84
85pub(crate) fn parse_macro(
86 db: &dyn AstDatabase,
87 macro_file: MacroFile,
88) -> Option<Parse<SyntaxNode>> {
89 let _p = profile("parse_macro_query");
90 let macro_call_id = macro_file.macro_call_id;
91 let tt = db
92 .macro_expand(macro_call_id)
93 .map_err(|err| {
94 // Note:
95 // The final goal we would like to make all parse_macro success,
96 // such that the following log will not call anyway.
97 log::warn!("fail on macro_parse: (reason: {})", err,);
98 })
99 .ok()?;
100 match macro_file.macro_file_kind {
101 MacroFileKind::Items => mbe::token_tree_to_items(&tt).ok().map(Parse::to_syntax),
102 MacroFileKind::Expr => mbe::token_tree_to_expr(&tt).ok().map(Parse::to_syntax),
103 }
104}
diff --git a/crates/ra_hir_expand/src/either.rs b/crates/ra_hir_expand/src/either.rs
new file mode 100644
index 000000000..83583ef8b
--- /dev/null
+++ b/crates/ra_hir_expand/src/either.rs
@@ -0,0 +1,54 @@
1//! FIXME: write short doc here
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
4pub enum Either<A, B> {
5 A(A),
6 B(B),
7}
8
9impl<A, B> Either<A, B> {
10 pub fn either<R, F1, F2>(self, f1: F1, f2: F2) -> R
11 where
12 F1: FnOnce(A) -> R,
13 F2: FnOnce(B) -> R,
14 {
15 match self {
16 Either::A(a) => f1(a),
17 Either::B(b) => f2(b),
18 }
19 }
20 pub fn map<U, V, F1, F2>(self, f1: F1, f2: F2) -> Either<U, V>
21 where
22 F1: FnOnce(A) -> U,
23 F2: FnOnce(B) -> V,
24 {
25 match self {
26 Either::A(a) => Either::A(f1(a)),
27 Either::B(b) => Either::B(f2(b)),
28 }
29 }
30 pub fn map_a<U, F>(self, f: F) -> Either<U, B>
31 where
32 F: FnOnce(A) -> U,
33 {
34 self.map(f, |it| it)
35 }
36 pub fn a(self) -> Option<A> {
37 match self {
38 Either::A(it) => Some(it),
39 Either::B(_) => None,
40 }
41 }
42 pub fn b(self) -> Option<B> {
43 match self {
44 Either::A(_) => None,
45 Either::B(it) => Some(it),
46 }
47 }
48 pub fn as_ref(&self) -> Either<&A, &B> {
49 match self {
50 Either::A(it) => Either::A(it),
51 Either::B(it) => Either::B(it),
52 }
53 }
54}
diff --git a/crates/ra_hir_expand/src/hygiene.rs b/crates/ra_hir_expand/src/hygiene.rs
new file mode 100644
index 000000000..77428ec99
--- /dev/null
+++ b/crates/ra_hir_expand/src/hygiene.rs
@@ -0,0 +1,46 @@
1//! This modules handles hygiene information.
2//!
3//! Specifically, `ast` + `Hygiene` allows you to create a `Name`. Note that, at
4//! this moment, this is horribly incomplete and handles only `$crate`.
5use ra_db::CrateId;
6use ra_syntax::ast;
7
8use crate::{
9 db::AstDatabase,
10 either::Either,
11 name::{AsName, Name},
12 HirFileId, HirFileIdRepr,
13};
14
15#[derive(Debug)]
16pub struct Hygiene {
17 // This is what `$crate` expands to
18 def_crate: Option<CrateId>,
19}
20
21impl Hygiene {
22 pub fn new(db: &impl AstDatabase, file_id: HirFileId) -> Hygiene {
23 let def_crate = match file_id.0 {
24 HirFileIdRepr::FileId(_) => None,
25 HirFileIdRepr::MacroFile(macro_file) => {
26 let loc = db.lookup_intern_macro(macro_file.macro_call_id);
27 Some(loc.def.krate)
28 }
29 };
30 Hygiene { def_crate }
31 }
32
33 pub fn new_unhygienic() -> Hygiene {
34 Hygiene { def_crate: None }
35 }
36
37 // FIXME: this should just return name
38 pub fn name_ref_to_name(&self, name_ref: ast::NameRef) -> Either<Name, CrateId> {
39 if let Some(def_crate) = self.def_crate {
40 if name_ref.text() == "$crate" {
41 return Either::B(def_crate);
42 }
43 }
44 Either::A(name_ref.as_name())
45 }
46}
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs
new file mode 100644
index 000000000..5a0e5a19c
--- /dev/null
+++ b/crates/ra_hir_expand/src/lib.rs
@@ -0,0 +1,153 @@
1//! `ra_hir_expand` deals with macro expansion.
2//!
3//! Specifically, it implements a concept of `MacroFile` -- a file whose syntax
4//! tree originates not from the text of some `FileId`, but from some macro
5//! expansion.
6
7pub mod db;
8pub mod ast_id_map;
9pub mod either;
10pub mod name;
11pub mod hygiene;
12
13use std::hash::{Hash, Hasher};
14
15use ra_db::{salsa, CrateId, FileId};
16use ra_syntax::ast::{self, AstNode};
17
18use crate::ast_id_map::FileAstId;
19
20/// Input to the analyzer is a set of files, where each file is identified by
21/// `FileId` and contains source code. However, another source of source code in
22/// Rust are macros: each macro can be thought of as producing a "temporary
23/// file". To assign an id to such a file, we use the id of the macro call that
24/// produced the file. So, a `HirFileId` is either a `FileId` (source code
25/// written by user), or a `MacroCallId` (source code produced by macro).
26///
27/// What is a `MacroCallId`? Simplifying, it's a `HirFileId` of a file
28/// containing the call plus the offset of the macro call in the file. Note that
29/// this is a recursive definition! However, the size_of of `HirFileId` is
30/// finite (because everything bottoms out at the real `FileId`) and small
31/// (`MacroCallId` uses the location interner).
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
33pub struct HirFileId(HirFileIdRepr);
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
36enum HirFileIdRepr {
37 FileId(FileId),
38 MacroFile(MacroFile),
39}
40
41impl From<FileId> for HirFileId {
42 fn from(id: FileId) -> Self {
43 HirFileId(HirFileIdRepr::FileId(id))
44 }
45}
46
47impl From<MacroFile> for HirFileId {
48 fn from(id: MacroFile) -> Self {
49 HirFileId(HirFileIdRepr::MacroFile(id))
50 }
51}
52
53impl HirFileId {
54 /// For macro-expansion files, returns the file original source file the
55 /// expansion originated from.
56 pub fn original_file(self, db: &dyn db::AstDatabase) -> FileId {
57 match self.0 {
58 HirFileIdRepr::FileId(file_id) => file_id,
59 HirFileIdRepr::MacroFile(macro_file) => {
60 let loc = db.lookup_intern_macro(macro_file.macro_call_id);
61 loc.ast_id.file_id().original_file(db)
62 }
63 }
64 }
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
68pub struct MacroFile {
69 macro_call_id: MacroCallId,
70 macro_file_kind: MacroFileKind,
71}
72
73#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
74pub enum MacroFileKind {
75 Items,
76 Expr,
77}
78
79/// `MacroCallId` identifies a particular macro invocation, like
80/// `println!("Hello, {}", world)`.
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
82pub struct MacroCallId(salsa::InternId);
83impl salsa::InternKey for MacroCallId {
84 fn from_intern_id(v: salsa::InternId) -> Self {
85 MacroCallId(v)
86 }
87 fn as_intern_id(&self) -> salsa::InternId {
88 self.0
89 }
90}
91
92#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
93pub struct MacroDefId {
94 pub krate: CrateId,
95 pub ast_id: AstId<ast::MacroCall>,
96}
97
98#[derive(Debug, Clone, PartialEq, Eq, Hash)]
99pub struct MacroCallLoc {
100 pub def: MacroDefId,
101 pub ast_id: AstId<ast::MacroCall>,
102}
103
104impl MacroCallId {
105 pub fn as_file(self, kind: MacroFileKind) -> HirFileId {
106 let macro_file = MacroFile { macro_call_id: self, macro_file_kind: kind };
107 macro_file.into()
108 }
109}
110
111/// `AstId` points to an AST node in any file.
112///
113/// It is stable across reparses, and can be used as salsa key/value.
114// FIXME: isn't this just a `Source<FileAstId<N>>` ?
115#[derive(Debug)]
116pub struct AstId<N: AstNode> {
117 file_id: HirFileId,
118 file_ast_id: FileAstId<N>,
119}
120
121impl<N: AstNode> Clone for AstId<N> {
122 fn clone(&self) -> AstId<N> {
123 *self
124 }
125}
126impl<N: AstNode> Copy for AstId<N> {}
127
128impl<N: AstNode> PartialEq for AstId<N> {
129 fn eq(&self, other: &Self) -> bool {
130 (self.file_id, self.file_ast_id) == (other.file_id, other.file_ast_id)
131 }
132}
133impl<N: AstNode> Eq for AstId<N> {}
134impl<N: AstNode> Hash for AstId<N> {
135 fn hash<H: Hasher>(&self, hasher: &mut H) {
136 (self.file_id, self.file_ast_id).hash(hasher);
137 }
138}
139
140impl<N: AstNode> AstId<N> {
141 pub fn new(file_id: HirFileId, file_ast_id: FileAstId<N>) -> AstId<N> {
142 AstId { file_id, file_ast_id }
143 }
144
145 pub fn file_id(&self) -> HirFileId {
146 self.file_id
147 }
148
149 pub fn to_node(&self, db: &dyn db::AstDatabase) -> N {
150 let root = db.parse_or_expand(self.file_id).unwrap();
151 db.ast_id_map(self.file_id).get(self.file_ast_id).to_node(&root)
152 }
153}
diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs
new file mode 100644
index 000000000..720896ee8
--- /dev/null
+++ b/crates/ra_hir_expand/src/name.rs
@@ -0,0 +1,142 @@
1//! FIXME: write short doc here
2
3use std::fmt;
4
5use ra_syntax::{ast, SmolStr};
6
7/// `Name` is a wrapper around string, which is used in hir for both references
8/// and declarations. In theory, names should also carry hygiene info, but we are
9/// not there yet!
10#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
11pub struct Name(Repr);
12
13#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
14enum Repr {
15 Text(SmolStr),
16 TupleField(usize),
17}
18
19impl fmt::Display for Name {
20 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21 match &self.0 {
22 Repr::Text(text) => fmt::Display::fmt(&text, f),
23 Repr::TupleField(idx) => fmt::Display::fmt(&idx, f),
24 }
25 }
26}
27
28impl Name {
29 /// Note: this is private to make creating name from random string hard.
30 /// Hopefully, this should allow us to integrate hygiene cleaner in the
31 /// future, and to switch to interned representation of names.
32 const fn new_text(text: SmolStr) -> Name {
33 Name(Repr::Text(text))
34 }
35
36 pub fn new_tuple_field(idx: usize) -> Name {
37 Name(Repr::TupleField(idx))
38 }
39
40 /// Shortcut to create inline plain text name
41 const fn new_inline_ascii(len: usize, text: &[u8]) -> Name {
42 Name::new_text(SmolStr::new_inline_from_ascii(len, text))
43 }
44
45 /// Resolve a name from the text of token.
46 fn resolve(raw_text: &SmolStr) -> Name {
47 let raw_start = "r#";
48 if raw_text.as_str().starts_with(raw_start) {
49 Name::new_text(SmolStr::new(&raw_text[raw_start.len()..]))
50 } else {
51 Name::new_text(raw_text.clone())
52 }
53 }
54
55 pub fn missing() -> Name {
56 Name::new_text("[missing name]".into())
57 }
58
59 pub fn as_tuple_index(&self) -> Option<usize> {
60 match self.0 {
61 Repr::TupleField(idx) => Some(idx),
62 _ => None,
63 }
64 }
65}
66
67pub trait AsName {
68 fn as_name(&self) -> Name;
69}
70
71impl AsName for ast::NameRef {
72 fn as_name(&self) -> Name {
73 match self.as_tuple_field() {
74 Some(idx) => Name::new_tuple_field(idx),
75 None => Name::resolve(self.text()),
76 }
77 }
78}
79
80impl AsName for ast::Name {
81 fn as_name(&self) -> Name {
82 Name::resolve(self.text())
83 }
84}
85
86impl AsName for ast::FieldKind {
87 fn as_name(&self) -> Name {
88 match self {
89 ast::FieldKind::Name(nr) => nr.as_name(),
90 ast::FieldKind::Index(idx) => Name::new_tuple_field(idx.text().parse().unwrap()),
91 }
92 }
93}
94
95impl AsName for ra_db::Dependency {
96 fn as_name(&self) -> Name {
97 Name::new_text(self.name.clone())
98 }
99}
100
101// Primitives
102pub const ISIZE: Name = Name::new_inline_ascii(5, b"isize");
103pub const I8: Name = Name::new_inline_ascii(2, b"i8");
104pub const I16: Name = Name::new_inline_ascii(3, b"i16");
105pub const I32: Name = Name::new_inline_ascii(3, b"i32");
106pub const I64: Name = Name::new_inline_ascii(3, b"i64");
107pub const I128: Name = Name::new_inline_ascii(4, b"i128");
108pub const USIZE: Name = Name::new_inline_ascii(5, b"usize");
109pub const U8: Name = Name::new_inline_ascii(2, b"u8");
110pub const U16: Name = Name::new_inline_ascii(3, b"u16");
111pub const U32: Name = Name::new_inline_ascii(3, b"u32");
112pub const U64: Name = Name::new_inline_ascii(3, b"u64");
113pub const U128: Name = Name::new_inline_ascii(4, b"u128");
114pub const F32: Name = Name::new_inline_ascii(3, b"f32");
115pub const F64: Name = Name::new_inline_ascii(3, b"f64");
116pub const BOOL: Name = Name::new_inline_ascii(4, b"bool");
117pub const CHAR: Name = Name::new_inline_ascii(4, b"char");
118pub const STR: Name = Name::new_inline_ascii(3, b"str");
119
120// Special names
121pub const SELF_PARAM: Name = Name::new_inline_ascii(4, b"self");
122pub const SELF_TYPE: Name = Name::new_inline_ascii(4, b"Self");
123pub const MACRO_RULES: Name = Name::new_inline_ascii(11, b"macro_rules");
124
125// Components of known path (value or mod name)
126pub const STD: Name = Name::new_inline_ascii(3, b"std");
127pub const ITER: Name = Name::new_inline_ascii(4, b"iter");
128pub const OPS: Name = Name::new_inline_ascii(3, b"ops");
129pub const FUTURE: Name = Name::new_inline_ascii(6, b"future");
130pub const RESULT: Name = Name::new_inline_ascii(6, b"result");
131pub const BOXED: Name = Name::new_inline_ascii(5, b"boxed");
132
133// Components of known path (type name)
134pub const INTO_ITERATOR_TYPE: Name = Name::new_inline_ascii(12, b"IntoIterator");
135pub const ITEM_TYPE: Name = Name::new_inline_ascii(4, b"Item");
136pub const TRY_TYPE: Name = Name::new_inline_ascii(3, b"Try");
137pub const OK_TYPE: Name = Name::new_inline_ascii(2, b"Ok");
138pub const FUTURE_TYPE: Name = Name::new_inline_ascii(6, b"Future");
139pub const RESULT_TYPE: Name = Name::new_inline_ascii(6, b"Result");
140pub const OUTPUT_TYPE: Name = Name::new_inline_ascii(6, b"Output");
141pub const TARGET_TYPE: Name = Name::new_inline_ascii(6, b"Target");
142pub const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box");