aboutsummaryrefslogtreecommitdiff
path: root/crates
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
parent88c6109897417e7ab815ea1711f49545bff94601 (diff)
Forbid <T>::foo syntax in mod paths
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/assists/add_import.rs2
-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
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs4
-rw-r--r--crates/ra_hir_ty/src/lower.rs6
7 files changed, 27 insertions, 20 deletions
diff --git a/crates/ra_assists/src/assists/add_import.rs b/crates/ra_assists/src/assists/add_import.rs
index ceffee9b8..b8752cbad 100644
--- a/crates/ra_assists/src/assists/add_import.rs
+++ b/crates/ra_assists/src/assists/add_import.rs
@@ -590,7 +590,7 @@ fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> {
590 } 590 }
591 ps.push(chain.into()); 591 ps.push(chain.into());
592 } 592 }
593 hir::PathKind::Type(_) | hir::PathKind::DollarCrate(_) => return None, 593 hir::PathKind::DollarCrate(_) => return None,
594 } 594 }
595 ps.extend(path.segments().iter().map(|it| it.name.to_string().into())); 595 ps.extend(path.segments().iter().map(|it| it.name.to_string().into()));
596 Some(ps) 596 Some(ps)
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() {
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs
index 3bae0ca6c..402a89386 100644
--- a/crates/ra_hir_ty/src/infer/path.rs
+++ b/crates/ra_hir_ty/src/infer/path.rs
@@ -3,7 +3,7 @@
3use std::iter; 3use std::iter;
4 4
5use hir_def::{ 5use hir_def::{
6 path::{Path, PathKind, PathSegment}, 6 path::{Path, PathSegment},
7 resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, 7 resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
8 AssocItemId, ContainerId, Lookup, 8 AssocItemId, ContainerId, Lookup,
9}; 9};
@@ -32,7 +32,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
32 path: &Path, 32 path: &Path,
33 id: ExprOrPatId, 33 id: ExprOrPatId,
34 ) -> Option<Ty> { 34 ) -> Option<Ty> {
35 let (value, self_subst) = if let PathKind::Type(type_ref) = path.kind() { 35 let (value, self_subst) = if let Some(type_ref) = path.type_anchor() {
36 if path.segments().is_empty() { 36 if path.segments().is_empty() {
37 // This can't actually happen syntax-wise 37 // This can't actually happen syntax-wise
38 return None; 38 return None;
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index a4ddfc8ef..2b84309d7 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -11,7 +11,7 @@ use std::sync::Arc;
11use hir_def::{ 11use hir_def::{
12 builtin_type::BuiltinType, 12 builtin_type::BuiltinType,
13 generics::WherePredicate, 13 generics::WherePredicate,
14 path::{GenericArg, Path, PathKind, PathSegment, PathSegments}, 14 path::{GenericArg, Path, PathSegment, PathSegments},
15 resolver::{HasResolver, Resolver, TypeNs}, 15 resolver::{HasResolver, Resolver, TypeNs},
16 type_ref::{TypeBound, TypeRef}, 16 type_ref::{TypeBound, TypeRef},
17 AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, 17 AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId,
@@ -101,7 +101,7 @@ impl Ty {
101 TypeRef::Path(path) => path, 101 TypeRef::Path(path) => path,
102 _ => return None, 102 _ => return None,
103 }; 103 };
104 if let PathKind::Type(_) = path.kind() { 104 if path.type_anchor().is_some() {
105 return None; 105 return None;
106 } 106 }
107 if path.segments().len() > 1 { 107 if path.segments().len() > 1 {
@@ -202,7 +202,7 @@ impl Ty {
202 202
203 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { 203 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty {
204 // Resolve the path (in type namespace) 204 // Resolve the path (in type namespace)
205 if let PathKind::Type(type_ref) = path.kind() { 205 if let Some(type_ref) = path.type_anchor() {
206 let ty = Ty::from_hir(db, resolver, &type_ref); 206 let ty = Ty::from_hir(db, resolver, &type_ref);
207 return Ty::from_type_relative_path(db, resolver, ty, path.segments()); 207 return Ty::from_type_relative_path(db, resolver, ty, path.segments());
208 } 208 }