diff options
author | Aleksey Kladov <[email protected]> | 2019-12-18 16:41:33 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-12-18 16:41:33 +0000 |
commit | 04715cbe1caf92e55d393a352a12454ba958845e (patch) | |
tree | 8c4a839f9b3ac037429d20b568c5a573c7d65825 /crates/ra_hir_def/src | |
parent | 88c6109897417e7ab815ea1711f49545bff94601 (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.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/path_resolution.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir_def/src/path.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir_def/src/path/lower.rs | 6 |
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(¯o_call), | 44 | db.ast_id_map(self.current_file_id).ast_id(¯o_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)] |
86 | pub struct Path { | 84 | pub 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 { | |||
226 | impl From<Name> for Path { | 231 | impl 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. |
23 | pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> { | 23 | pub(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() { |