aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-12-18 16:41:33 +0000
committerAleksey Kladov <[email protected]>2019-12-18 16:41:33 +0000
commit04715cbe1caf92e55d393a352a12454ba958845e (patch)
tree8c4a839f9b3ac037429d20b568c5a573c7d65825 /crates/ra_hir_def/src
parent88c6109897417e7ab815ea1711f49545bff94601 (diff)
Forbid <T>::foo syntax in mod paths
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r--crates/ra_hir_def/src/body.rs12
-rw-r--r--crates/ra_hir_def/src/nameres/path_resolution.rs5
-rw-r--r--crates/ra_hir_def/src/path.rs12
-rw-r--r--crates/ra_hir_def/src/path/lower.rs6
4 files changed, 21 insertions, 14 deletions
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 7787cb87f..d4cab0561 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -15,7 +15,7 @@ use crate::{
15 db::DefDatabase, 15 db::DefDatabase,
16 expr::{Expr, ExprId, Pat, PatId}, 16 expr::{Expr, ExprId, Pat, PatId},
17 nameres::{BuiltinShadowMode, CrateDefMap}, 17 nameres::{BuiltinShadowMode, CrateDefMap},
18 path::Path, 18 path::{ModPath, Path},
19 src::HasSource, 19 src::HasSource,
20 DefWithBodyId, HasModule, Lookup, ModuleId, 20 DefWithBodyId, HasModule, Lookup, ModuleId,
21}; 21};
@@ -44,7 +44,7 @@ impl Expander {
44 db.ast_id_map(self.current_file_id).ast_id(&macro_call), 44 db.ast_id_map(self.current_file_id).ast_id(&macro_call),
45 ); 45 );
46 46
47 if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) { 47 if let Some(path) = macro_call.path().and_then(|path| self.parse_mod_path(path)) {
48 if let Some(def) = self.resolve_path_as_macro(db, &path) { 48 if let Some(def) = self.resolve_path_as_macro(db, &path) {
49 let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id)); 49 let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id));
50 let file_id = call_id.as_file(); 50 let file_id = call_id.as_file();
@@ -81,9 +81,13 @@ impl Expander {
81 Path::from_src(path, &self.hygiene) 81 Path::from_src(path, &self.hygiene)
82 } 82 }
83 83
84 fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> { 84 fn parse_mod_path(&mut self, path: ast::Path) -> Option<ModPath> {
85 ModPath::from_src(path, &self.hygiene)
86 }
87
88 fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &ModPath) -> Option<MacroDefId> {
85 self.crate_def_map 89 self.crate_def_map
86 .resolve_path(db, self.module.local_id, path.mod_path(), BuiltinShadowMode::Other) 90 .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other)
87 .0 91 .0
88 .take_macros() 92 .take_macros()
89 } 93 }
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs
index 1dbc4f371..2dd779b66 100644
--- a/crates/ra_hir_def/src/nameres/path_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/path_resolution.rs
@@ -145,11 +145,6 @@ impl CrateDefMap {
145 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude 145 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
146 } 146 }
147 } 147 }
148 PathKind::Type(_) => {
149 // This is handled in `infer::infer_path_expr`
150 // The result returned here does not matter
151 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
152 }
153 }; 148 };
154 149
155 for (i, segment) in segments { 150 for (i, segment) in segments {
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index e38d924fa..1e2da6b48 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -26,8 +26,6 @@ pub enum PathKind {
26 Crate, 26 Crate,
27 /// Absolute path (::foo) 27 /// Absolute path (::foo)
28 Abs, 28 Abs,
29 /// Type based path like `<T>::foo`
30 Type(Box<TypeRef>),
31 /// `$crate` from macro expansion 29 /// `$crate` from macro expansion
32 DollarCrate(CrateId), 30 DollarCrate(CrateId),
33} 31}
@@ -84,6 +82,8 @@ impl ModPath {
84 82
85#[derive(Debug, Clone, PartialEq, Eq, Hash)] 83#[derive(Debug, Clone, PartialEq, Eq, Hash)]
86pub struct Path { 84pub struct Path {
85 /// Type based path like `<T>::foo`
86 type_anchor: Option<Box<TypeRef>>,
87 mod_path: ModPath, 87 mod_path: ModPath,
88 /// Invariant: the same len as self.path.segments 88 /// Invariant: the same len as self.path.segments
89 generic_args: Vec<Option<Arc<GenericArgs>>>, 89 generic_args: Vec<Option<Arc<GenericArgs>>>,
@@ -126,7 +126,7 @@ impl Path {
126 126
127 /// Converts an `ast::NameRef` into a single-identifier `Path`. 127 /// Converts an `ast::NameRef` into a single-identifier `Path`.
128 pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path { 128 pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path {
129 Path { mod_path: name_ref.as_name().into(), generic_args: vec![None] } 129 Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] }
130 } 130 }
131 131
132 /// `true` if this path is just a standalone `self` 132 /// `true` if this path is just a standalone `self`
@@ -138,6 +138,10 @@ impl Path {
138 &self.mod_path.kind 138 &self.mod_path.kind
139 } 139 }
140 140
141 pub fn type_anchor(&self) -> Option<&TypeRef> {
142 self.type_anchor.as_ref().map(|it| &**it)
143 }
144
141 pub fn segments(&self) -> PathSegments<'_> { 145 pub fn segments(&self) -> PathSegments<'_> {
142 PathSegments { 146 PathSegments {
143 segments: self.mod_path.segments.as_slice(), 147 segments: self.mod_path.segments.as_slice(),
@@ -154,6 +158,7 @@ impl Path {
154 return None; 158 return None;
155 } 159 }
156 let res = Path { 160 let res = Path {
161 type_anchor: self.type_anchor.clone(),
157 mod_path: ModPath { 162 mod_path: ModPath {
158 kind: self.mod_path.kind.clone(), 163 kind: self.mod_path.kind.clone(),
159 segments: self.mod_path.segments[..self.mod_path.segments.len() - 1].to_vec(), 164 segments: self.mod_path.segments[..self.mod_path.segments.len() - 1].to_vec(),
@@ -226,6 +231,7 @@ impl GenericArgs {
226impl From<Name> for Path { 231impl From<Name> for Path {
227 fn from(name: Name) -> Path { 232 fn from(name: Name) -> Path {
228 Path { 233 Path {
234 type_anchor: None,
229 mod_path: ModPath::from_simple_segments(PathKind::Plain, iter::once(name)), 235 mod_path: ModPath::from_simple_segments(PathKind::Plain, iter::once(name)),
230 generic_args: vec![None], 236 generic_args: vec![None],
231 } 237 }
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs
index c71b52d89..62aafd508 100644
--- a/crates/ra_hir_def/src/path/lower.rs
+++ b/crates/ra_hir_def/src/path/lower.rs
@@ -22,6 +22,7 @@ pub(super) use lower_use::lower_use_tree;
22/// It correctly handles `$crate` based path from macro call. 22/// It correctly handles `$crate` based path from macro call.
23pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> { 23pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
24 let mut kind = PathKind::Plain; 24 let mut kind = PathKind::Plain;
25 let mut type_anchor = None;
25 let mut segments = Vec::new(); 26 let mut segments = Vec::new();
26 let mut generic_args = Vec::new(); 27 let mut generic_args = Vec::new();
27 loop { 28 loop {
@@ -63,7 +64,8 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
63 match trait_ref { 64 match trait_ref {
64 // <T>::foo 65 // <T>::foo
65 None => { 66 None => {
66 kind = PathKind::Type(Box::new(self_type)); 67 type_anchor = Some(Box::new(self_type));
68 kind = PathKind::Plain;
67 } 69 }
68 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo 70 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
69 Some(trait_ref) => { 71 Some(trait_ref) => {
@@ -111,7 +113,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
111 segments.reverse(); 113 segments.reverse();
112 generic_args.reverse(); 114 generic_args.reverse();
113 let mod_path = ModPath { kind, segments }; 115 let mod_path = ModPath { kind, segments };
114 return Some(Path { mod_path, generic_args }); 116 return Some(Path { type_anchor, mod_path, generic_args });
115 117
116 fn qualifier(path: &ast::Path) -> Option<ast::Path> { 118 fn qualifier(path: &ast::Path) -> Option<ast::Path> {
117 if let Some(q) = path.qualifier() { 119 if let Some(q) = path.qualifier() {