aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r--crates/ra_hir_def/src/attr.rs19
-rw-r--r--crates/ra_hir_def/src/either.rs54
-rw-r--r--crates/ra_hir_def/src/lib.rs2
-rw-r--r--crates/ra_hir_def/src/name.rs142
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs55
-rw-r--r--crates/ra_hir_def/src/path.rs115
6 files changed, 86 insertions, 301 deletions
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 248f03cdf..0e961ca12 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -2,7 +2,7 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_expand::db::AstDatabase; 5use hir_expand::hygiene::Hygiene;
6use mbe::ast_to_token_tree; 6use mbe::ast_to_token_tree;
7use ra_cfg::CfgOptions; 7use ra_cfg::CfgOptions;
8use ra_syntax::{ 8use ra_syntax::{
@@ -11,7 +11,7 @@ use ra_syntax::{
11}; 11};
12use tt::Subtree; 12use tt::Subtree;
13 13
14use crate::{path::Path, HirFileId, Source}; 14use crate::path::Path;
15 15
16#[derive(Debug, Clone, PartialEq, Eq)] 16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct Attr { 17pub struct Attr {
@@ -26,11 +26,8 @@ pub enum AttrInput {
26} 26}
27 27
28impl Attr { 28impl Attr {
29 pub(crate) fn from_src( 29 pub(crate) fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> {
30 Source { file_id, ast }: Source<ast::Attr>, 30 let path = Path::from_src(ast.path()?, hygiene)?;
31 db: &impl AstDatabase,
32 ) -> Option<Attr> {
33 let path = Path::from_src(Source { file_id, ast: ast.path()? }, db)?;
34 let input = match ast.input() { 31 let input = match ast.input() {
35 None => None, 32 None => None,
36 Some(ast::AttrInput::Literal(lit)) => { 33 Some(ast::AttrInput::Literal(lit)) => {
@@ -46,17 +43,13 @@ impl Attr {
46 Some(Attr { path, input }) 43 Some(Attr { path, input })
47 } 44 }
48 45
49 pub fn from_attrs_owner( 46 pub fn from_attrs_owner(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Option<Arc<[Attr]>> {
50 file_id: HirFileId,
51 owner: &dyn AttrsOwner,
52 db: &impl AstDatabase,
53 ) -> Option<Arc<[Attr]>> {
54 let mut attrs = owner.attrs().peekable(); 47 let mut attrs = owner.attrs().peekable();
55 if attrs.peek().is_none() { 48 if attrs.peek().is_none() {
56 // Avoid heap allocation 49 // Avoid heap allocation
57 return None; 50 return None;
58 } 51 }
59 Some(attrs.flat_map(|ast| Attr::from_src(Source { file_id, ast }, db)).collect()) 52 Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).collect())
60 } 53 }
61 54
62 pub fn is_simple_atom(&self, name: &str) -> bool { 55 pub fn is_simple_atom(&self, name: &str) -> bool {
diff --git a/crates/ra_hir_def/src/either.rs b/crates/ra_hir_def/src/either.rs
deleted file mode 100644
index 83583ef8b..000000000
--- a/crates/ra_hir_def/src/either.rs
+++ /dev/null
@@ -1,54 +0,0 @@
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_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 95d503325..7a6c7b301 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -8,9 +8,7 @@
8//! actually true. 8//! actually true.
9 9
10pub mod db; 10pub mod db;
11pub mod either;
12pub mod attr; 11pub mod attr;
13pub mod name;
14pub mod path; 12pub mod path;
15pub mod type_ref; 13pub mod type_ref;
16 14
diff --git a/crates/ra_hir_def/src/name.rs b/crates/ra_hir_def/src/name.rs
deleted file mode 100644
index 720896ee8..000000000
--- a/crates/ra_hir_def/src/name.rs
+++ /dev/null
@@ -1,142 +0,0 @@
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");
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 86b4fef96..86c05d602 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -2,21 +2,20 @@
2 2
3use std::{ops::Index, sync::Arc}; 3use std::{ops::Index, sync::Arc};
4 4
5use hir_expand::{ast_id_map::AstIdMap, db::AstDatabase}; 5use hir_expand::{
6 ast_id_map::AstIdMap,
7 db::AstDatabase,
8 either::Either,
9 hygiene::Hygiene,
10 name::{AsName, Name},
11};
6use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; 12use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
7use ra_syntax::{ 13use ra_syntax::{
8 ast::{self, AttrsOwner, NameOwner}, 14 ast::{self, AttrsOwner, NameOwner},
9 AstNode, AstPtr, SourceFile, 15 AstNode, AstPtr, SourceFile,
10}; 16};
11 17
12use crate::{ 18use crate::{attr::Attr, db::DefDatabase2, path::Path, FileAstId, HirFileId, ModuleSource, Source};
13 attr::Attr,
14 db::DefDatabase2,
15 either::Either,
16 name::{AsName, Name},
17 path::Path,
18 FileAstId, HirFileId, ModuleSource, Source,
19};
20 19
21/// `RawItems` is a set of top-level items in a file (except for impls). 20/// `RawItems` is a set of top-level items in a file (except for impls).
22/// 21///
@@ -40,10 +39,8 @@ pub struct ImportSourceMap {
40type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>; 39type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>;
41type ImportSource = Either<ast::UseTree, ast::ExternCrateItem>; 40type ImportSource = Either<ast::UseTree, ast::ExternCrateItem>;
42 41
43impl ImportSourcePtr { 42fn to_node(ptr: ImportSourcePtr, file: &SourceFile) -> ImportSource {
44 fn to_node(self, file: &SourceFile) -> ImportSource { 43 ptr.map(|ptr| ptr.to_node(file.syntax()), |ptr| ptr.to_node(file.syntax()))
45 self.map(|ptr| ptr.to_node(file.syntax()), |ptr| ptr.to_node(file.syntax()))
46 }
47} 44}
48 45
49impl ImportSourceMap { 46impl ImportSourceMap {
@@ -57,7 +54,7 @@ impl ImportSourceMap {
57 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(), 54 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
58 }; 55 };
59 56
60 self.map[import].to_node(&file) 57 to_node(self.map[import], &file)
61 } 58 }
62} 59}
63 60
@@ -78,7 +75,7 @@ impl RawItems {
78 source_ast_id_map: db.ast_id_map(file_id), 75 source_ast_id_map: db.ast_id_map(file_id),
79 source_map: ImportSourceMap::default(), 76 source_map: ImportSourceMap::default(),
80 file_id, 77 file_id,
81 db, 78 hygiene: Hygiene::new(db, file_id),
82 }; 79 };
83 if let Some(node) = db.parse_or_expand(file_id) { 80 if let Some(node) = db.parse_or_expand(file_id) {
84 if let Some(source_file) = ast::SourceFile::cast(node.clone()) { 81 if let Some(source_file) = ast::SourceFile::cast(node.clone()) {
@@ -204,15 +201,15 @@ pub struct MacroData {
204 pub export: bool, 201 pub export: bool,
205} 202}
206 203
207struct RawItemsCollector<DB> { 204struct RawItemsCollector {
208 raw_items: RawItems, 205 raw_items: RawItems,
209 source_ast_id_map: Arc<AstIdMap>, 206 source_ast_id_map: Arc<AstIdMap>,
210 source_map: ImportSourceMap, 207 source_map: ImportSourceMap,
211 file_id: HirFileId, 208 file_id: HirFileId,
212 db: DB, 209 hygiene: Hygiene,
213} 210}
214 211
215impl<DB: AstDatabase> RawItemsCollector<&DB> { 212impl RawItemsCollector {
216 fn process_module(&mut self, current_module: Option<Module>, body: impl ast::ModuleItemOwner) { 213 fn process_module(&mut self, current_module: Option<Module>, body: impl ast::ModuleItemOwner) {
217 for item_or_macro in body.items_with_macros() { 214 for item_or_macro in body.items_with_macros() {
218 match item_or_macro { 215 match item_or_macro {
@@ -309,9 +306,10 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> {
309 let is_prelude = use_item.has_atom_attr("prelude_import"); 306 let is_prelude = use_item.has_atom_attr("prelude_import");
310 let attrs = self.parse_attrs(&use_item); 307 let attrs = self.parse_attrs(&use_item);
311 308
309 let mut buf = Vec::new();
312 Path::expand_use_item( 310 Path::expand_use_item(
313 Source { ast: use_item, file_id: self.file_id }, 311 Source { ast: use_item, file_id: self.file_id },
314 self.db, 312 &self.hygiene,
315 |path, use_tree, is_glob, alias| { 313 |path, use_tree, is_glob, alias| {
316 let import_data = ImportData { 314 let import_data = ImportData {
317 path, 315 path,
@@ -321,14 +319,12 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> {
321 is_extern_crate: false, 319 is_extern_crate: false,
322 is_macro_use: false, 320 is_macro_use: false,
323 }; 321 };
324 self.push_import( 322 buf.push((import_data, Either::A(AstPtr::new(use_tree))));
325 current_module,
326 attrs.clone(),
327 import_data,
328 Either::A(AstPtr::new(use_tree)),
329 );
330 }, 323 },
331 ) 324 );
325 for (import_data, ptr) in buf {
326 self.push_import(current_module, attrs.clone(), import_data, ptr);
327 }
332 } 328 }
333 329
334 fn add_extern_crate_item( 330 fn add_extern_crate_item(
@@ -361,10 +357,7 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> {
361 357
362 fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) { 358 fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) {
363 let attrs = self.parse_attrs(&m); 359 let attrs = self.parse_attrs(&m);
364 let path = match m 360 let path = match m.path().and_then(|path| Path::from_src(path, &self.hygiene)) {
365 .path()
366 .and_then(|path| Path::from_src(Source { ast: path, file_id: self.file_id }, self.db))
367 {
368 Some(it) => it, 361 Some(it) => it,
369 _ => return, 362 _ => return,
370 }; 363 };
@@ -402,6 +395,6 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> {
402 } 395 }
403 396
404 fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { 397 fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs {
405 Attr::from_attrs_owner(self.file_id, item, self.db) 398 Attr::from_attrs_owner(item, &self.hygiene)
406 } 399 }
407} 400}
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index fe060437d..04039376f 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -2,18 +2,18 @@
2 2
3use std::{iter, sync::Arc}; 3use std::{iter, sync::Arc};
4 4
5use hir_expand::db::AstDatabase; 5use hir_expand::{
6 either::Either,
7 hygiene::Hygiene,
8 name::{self, AsName, Name},
9};
6use ra_db::CrateId; 10use ra_db::CrateId;
7use ra_syntax::{ 11use ra_syntax::{
8 ast::{self, NameOwner, TypeAscriptionOwner}, 12 ast::{self, NameOwner, TypeAscriptionOwner},
9 AstNode, 13 AstNode,
10}; 14};
11 15
12use crate::{ 16use crate::{type_ref::TypeRef, Source};
13 name::{self, AsName, Name},
14 type_ref::TypeRef,
15 Source,
16};
17 17
18#[derive(Debug, Clone, PartialEq, Eq, Hash)] 18#[derive(Debug, Clone, PartialEq, Eq, Hash)]
19pub struct Path { 19pub struct Path {
@@ -68,11 +68,11 @@ impl Path {
68 /// Calls `cb` with all paths, represented by this use item. 68 /// Calls `cb` with all paths, represented by this use item.
69 pub fn expand_use_item( 69 pub fn expand_use_item(
70 item_src: Source<ast::UseItem>, 70 item_src: Source<ast::UseItem>,
71 db: &impl AstDatabase, 71 hygiene: &Hygiene,
72 mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>), 72 mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
73 ) { 73 ) {
74 if let Some(tree) = item_src.ast.use_tree() { 74 if let Some(tree) = item_src.ast.use_tree() {
75 expand_use_tree(None, tree, &|| item_src.file_id.macro_crate(db), &mut cb); 75 expand_use_tree(None, tree, hygiene, &mut cb);
76 } 76 }
77 } 77 }
78 78
@@ -89,17 +89,12 @@ impl Path {
89 /// Converts an `ast::Path` to `Path`. Works with use trees. 89 /// Converts an `ast::Path` to `Path`. Works with use trees.
90 /// DEPRECATED: It does not handle `$crate` from macro call. 90 /// DEPRECATED: It does not handle `$crate` from macro call.
91 pub fn from_ast(path: ast::Path) -> Option<Path> { 91 pub fn from_ast(path: ast::Path) -> Option<Path> {
92 Path::parse(path, &|| None) 92 Path::from_src(path, &Hygiene::new_unhygienic())
93 } 93 }
94 94
95 /// Converts an `ast::Path` to `Path`. Works with use trees. 95 /// Converts an `ast::Path` to `Path`. Works with use trees.
96 /// It correctly handles `$crate` based path from macro call. 96 /// It correctly handles `$crate` based path from macro call.
97 pub fn from_src(source: Source<ast::Path>, db: &impl AstDatabase) -> Option<Path> { 97 pub fn from_src(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
98 let file_id = source.file_id;
99 Path::parse(source.ast, &|| file_id.macro_crate(db))
100 }
101
102 fn parse(mut path: ast::Path, macro_crate: &impl Fn() -> Option<CrateId>) -> Option<Path> {
103 let mut kind = PathKind::Plain; 98 let mut kind = PathKind::Plain;
104 let mut segments = Vec::new(); 99 let mut segments = Vec::new();
105 loop { 100 loop {
@@ -110,26 +105,28 @@ impl Path {
110 } 105 }
111 106
112 match segment.kind()? { 107 match segment.kind()? {
113 ast::PathSegmentKind::Name(name) => { 108 ast::PathSegmentKind::Name(name_ref) => {
114 if name.text() == "$crate" { 109 // FIXME: this should just return name
115 if let Some(macro_crate) = macro_crate() { 110 match hygiene.name_ref_to_name(name_ref) {
116 kind = PathKind::DollarCrate(macro_crate); 111 Either::A(name) => {
112 let args = segment
113 .type_arg_list()
114 .and_then(GenericArgs::from_ast)
115 .or_else(|| {
116 GenericArgs::from_fn_like_path_ast(
117 segment.param_list(),
118 segment.ret_type(),
119 )
120 })
121 .map(Arc::new);
122 let segment = PathSegment { name, args_and_bindings: args };
123 segments.push(segment);
124 }
125 Either::B(crate_id) => {
126 kind = PathKind::DollarCrate(crate_id);
117 break; 127 break;
118 } 128 }
119 } 129 }
120
121 let args = segment
122 .type_arg_list()
123 .and_then(GenericArgs::from_ast)
124 .or_else(|| {
125 GenericArgs::from_fn_like_path_ast(
126 segment.param_list(),
127 segment.ret_type(),
128 )
129 })
130 .map(Arc::new);
131 let segment = PathSegment { name: name.as_name(), args_and_bindings: args };
132 segments.push(segment);
133 } 130 }
134 ast::PathSegmentKind::Type { type_ref, trait_ref } => { 131 ast::PathSegmentKind::Type { type_ref, trait_ref } => {
135 assert!(path.qualifier().is_none()); // this can only occur at the first segment 132 assert!(path.qualifier().is_none()); // this can only occur at the first segment
@@ -143,7 +140,7 @@ impl Path {
143 } 140 }
144 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo 141 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
145 Some(trait_ref) => { 142 Some(trait_ref) => {
146 let path = Path::parse(trait_ref.path()?, macro_crate)?; 143 let path = Path::from_src(trait_ref.path()?, hygiene)?;
147 kind = path.kind; 144 kind = path.kind;
148 let mut prefix_segments = path.segments; 145 let mut prefix_segments = path.segments;
149 prefix_segments.reverse(); 146 prefix_segments.reverse();
@@ -294,8 +291,8 @@ impl From<Name> for Path {
294fn expand_use_tree( 291fn expand_use_tree(
295 prefix: Option<Path>, 292 prefix: Option<Path>,
296 tree: ast::UseTree, 293 tree: ast::UseTree,
297 macro_crate: &impl Fn() -> Option<CrateId>, 294 hygiene: &Hygiene,
298 cb: &mut impl FnMut(Path, &ast::UseTree, bool, Option<Name>), 295 cb: &mut dyn FnMut(Path, &ast::UseTree, bool, Option<Name>),
299) { 296) {
300 if let Some(use_tree_list) = tree.use_tree_list() { 297 if let Some(use_tree_list) = tree.use_tree_list() {
301 let prefix = match tree.path() { 298 let prefix = match tree.path() {
@@ -303,13 +300,13 @@ fn expand_use_tree(
303 None => prefix, 300 None => prefix,
304 // E.g. `use something::{inner}` (prefix is `None`, path is `something`) 301 // E.g. `use something::{inner}` (prefix is `None`, path is `something`)
305 // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`) 302 // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
306 Some(path) => match convert_path(prefix, path, macro_crate) { 303 Some(path) => match convert_path(prefix, path, hygiene) {
307 Some(it) => Some(it), 304 Some(it) => Some(it),
308 None => return, // FIXME: report errors somewhere 305 None => return, // FIXME: report errors somewhere
309 }, 306 },
310 }; 307 };
311 for child_tree in use_tree_list.use_trees() { 308 for child_tree in use_tree_list.use_trees() {
312 expand_use_tree(prefix.clone(), child_tree, macro_crate, cb); 309 expand_use_tree(prefix.clone(), child_tree, hygiene, cb);
313 } 310 }
314 } else { 311 } else {
315 let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name()); 312 let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name());
@@ -326,7 +323,7 @@ fn expand_use_tree(
326 } 323 }
327 } 324 }
328 } 325 }
329 if let Some(path) = convert_path(prefix, ast_path, macro_crate) { 326 if let Some(path) = convert_path(prefix, ast_path, hygiene) {
330 let is_glob = tree.has_star(); 327 let is_glob = tree.has_star();
331 cb(path, &tree, is_glob, alias) 328 cb(path, &tree, is_glob, alias)
332 } 329 }
@@ -336,37 +333,36 @@ fn expand_use_tree(
336 } 333 }
337} 334}
338 335
339fn convert_path( 336fn convert_path(prefix: Option<Path>, path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
340 prefix: Option<Path>,
341 path: ast::Path,
342 macro_crate: &impl Fn() -> Option<CrateId>,
343) -> Option<Path> {
344 let prefix = if let Some(qual) = path.qualifier() { 337 let prefix = if let Some(qual) = path.qualifier() {
345 Some(convert_path(prefix, qual, macro_crate)?) 338 Some(convert_path(prefix, qual, hygiene)?)
346 } else { 339 } else {
347 prefix 340 prefix
348 }; 341 };
349 342
350 let segment = path.segment()?; 343 let segment = path.segment()?;
351 let res = match segment.kind()? { 344 let res = match segment.kind()? {
352 ast::PathSegmentKind::Name(name) => { 345 ast::PathSegmentKind::Name(name_ref) => {
353 if name.text() == "$crate" { 346 match hygiene.name_ref_to_name(name_ref) {
354 if let Some(krate) = macro_crate() { 347 Either::A(name) => {
348 // no type args in use
349 let mut res = prefix.unwrap_or_else(|| Path {
350 kind: PathKind::Plain,
351 segments: Vec::with_capacity(1),
352 });
353 res.segments.push(PathSegment {
354 name,
355 args_and_bindings: None, // no type args in use
356 });
357 res
358 }
359 Either::B(crate_id) => {
355 return Some(Path::from_simple_segments( 360 return Some(Path::from_simple_segments(
356 PathKind::DollarCrate(krate), 361 PathKind::DollarCrate(crate_id),
357 iter::empty(), 362 iter::empty(),
358 )); 363 ))
359 } 364 }
360 } 365 }
361
362 // no type args in use
363 let mut res = prefix
364 .unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) });
365 res.segments.push(PathSegment {
366 name: name.as_name(),
367 args_and_bindings: None, // no type args in use
368 });
369 res
370 } 366 }
371 ast::PathSegmentKind::CrateKw => { 367 ast::PathSegmentKind::CrateKw => {
372 if prefix.is_some() { 368 if prefix.is_some() {
@@ -395,8 +391,9 @@ fn convert_path(
395} 391}
396 392
397pub mod known { 393pub mod known {
394 use hir_expand::name;
395
398 use super::{Path, PathKind}; 396 use super::{Path, PathKind};
399 use crate::name;
400 397
401 pub fn std_iter_into_iterator() -> Path { 398 pub fn std_iter_into_iterator() -> Path {
402 Path::from_simple_segments( 399 Path::from_simple_segments(