diff options
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r-- | crates/ra_hir_def/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/ra_hir_def/src/adt.rs | 20 | ||||
-rw-r--r-- | crates/ra_hir_def/src/attr.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body.rs | 66 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 80 | ||||
-rw-r--r-- | crates/ra_hir_def/src/data.rs | 63 | ||||
-rw-r--r-- | crates/ra_hir_def/src/expr.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 14 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/tests/incremental.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir_def/src/path.rs | 26 | ||||
-rw-r--r-- | crates/ra_hir_def/src/path/lower.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir_def/src/type_ref.rs | 12 |
12 files changed, 202 insertions, 115 deletions
diff --git a/crates/ra_hir_def/Cargo.toml b/crates/ra_hir_def/Cargo.toml index 56e791e3e..b85358308 100644 --- a/crates/ra_hir_def/Cargo.toml +++ b/crates/ra_hir_def/Cargo.toml | |||
@@ -28,4 +28,4 @@ ra_cfg = { path = "../ra_cfg" } | |||
28 | tt = { path = "../ra_tt", package = "ra_tt" } | 28 | tt = { path = "../ra_tt", package = "ra_tt" } |
29 | 29 | ||
30 | [dev-dependencies] | 30 | [dev-dependencies] |
31 | insta = "0.15.0" | 31 | insta = "0.16.0" |
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index be4b0accb..7c0d93691 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs | |||
@@ -4,7 +4,6 @@ use std::sync::Arc; | |||
4 | 4 | ||
5 | use either::Either; | 5 | use either::Either; |
6 | use hir_expand::{ | 6 | use hir_expand::{ |
7 | hygiene::Hygiene, | ||
8 | name::{AsName, Name}, | 7 | name::{AsName, Name}, |
9 | InFile, | 8 | InFile, |
10 | }; | 9 | }; |
@@ -13,7 +12,7 @@ use ra_prof::profile; | |||
13 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; | 12 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; |
14 | 13 | ||
15 | use crate::{ | 14 | use crate::{ |
16 | attr::Attrs, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, | 15 | body::CfgExpander, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, |
17 | type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId, | 16 | type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId, |
18 | LocalStructFieldId, Lookup, ModuleId, StructId, UnionId, VariantId, | 17 | LocalStructFieldId, Lookup, ModuleId, StructId, UnionId, VariantId, |
19 | }; | 18 | }; |
@@ -125,8 +124,9 @@ fn lower_enum( | |||
125 | 124 | ||
126 | impl VariantData { | 125 | impl VariantData { |
127 | fn new(db: &dyn DefDatabase, flavor: InFile<ast::StructKind>, module_id: ModuleId) -> Self { | 126 | fn new(db: &dyn DefDatabase, flavor: InFile<ast::StructKind>, module_id: ModuleId) -> Self { |
127 | let mut expander = CfgExpander::new(db, flavor.file_id, module_id.krate); | ||
128 | let mut trace = Trace::new_for_arena(); | 128 | let mut trace = Trace::new_for_arena(); |
129 | match lower_struct(db, &mut trace, &flavor, module_id) { | 129 | match lower_struct(db, &mut expander, &mut trace, &flavor) { |
130 | StructKind::Tuple => VariantData::Tuple(trace.into_arena()), | 130 | StructKind::Tuple => VariantData::Tuple(trace.into_arena()), |
131 | StructKind::Record => VariantData::Record(trace.into_arena()), | 131 | StructKind::Record => VariantData::Record(trace.into_arena()), |
132 | StructKind::Unit => VariantData::Unit, | 132 | StructKind::Unit => VariantData::Unit, |
@@ -178,8 +178,9 @@ impl HasChildSource for VariantId { | |||
178 | it.lookup(db).container.module(db), | 178 | it.lookup(db).container.module(db), |
179 | ), | 179 | ), |
180 | }; | 180 | }; |
181 | let mut expander = CfgExpander::new(db, src.file_id, module_id.krate); | ||
181 | let mut trace = Trace::new_for_map(); | 182 | let mut trace = Trace::new_for_map(); |
182 | lower_struct(db, &mut trace, &src, module_id); | 183 | lower_struct(db, &mut expander, &mut trace, &src); |
183 | src.with_value(trace.into_map()) | 184 | src.with_value(trace.into_map()) |
184 | } | 185 | } |
185 | } | 186 | } |
@@ -193,16 +194,15 @@ pub enum StructKind { | |||
193 | 194 | ||
194 | fn lower_struct( | 195 | fn lower_struct( |
195 | db: &dyn DefDatabase, | 196 | db: &dyn DefDatabase, |
197 | expander: &mut CfgExpander, | ||
196 | trace: &mut Trace<StructFieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>, | 198 | trace: &mut Trace<StructFieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>, |
197 | ast: &InFile<ast::StructKind>, | 199 | ast: &InFile<ast::StructKind>, |
198 | module_id: ModuleId, | ||
199 | ) -> StructKind { | 200 | ) -> StructKind { |
200 | let crate_graph = db.crate_graph(); | ||
201 | match &ast.value { | 201 | match &ast.value { |
202 | ast::StructKind::Tuple(fl) => { | 202 | ast::StructKind::Tuple(fl) => { |
203 | for (i, fd) in fl.fields().enumerate() { | 203 | for (i, fd) in fl.fields().enumerate() { |
204 | let attrs = Attrs::new(&fd, &Hygiene::new(db.upcast(), ast.file_id)); | 204 | let attrs = expander.parse_attrs(&fd); |
205 | if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) { | 205 | if !expander.is_cfg_enabled(&attrs) { |
206 | continue; | 206 | continue; |
207 | } | 207 | } |
208 | 208 | ||
@@ -219,8 +219,8 @@ fn lower_struct( | |||
219 | } | 219 | } |
220 | ast::StructKind::Record(fl) => { | 220 | ast::StructKind::Record(fl) => { |
221 | for fd in fl.fields() { | 221 | for fd in fl.fields() { |
222 | let attrs = Attrs::new(&fd, &Hygiene::new(db.upcast(), ast.file_id)); | 222 | let attrs = expander.parse_attrs(&fd); |
223 | if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) { | 223 | if !expander.is_cfg_enabled(&attrs) { |
224 | continue; | 224 | continue; |
225 | } | 225 | } |
226 | 226 | ||
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index 7b0c506b1..2f2e3e5ba 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs | |||
@@ -93,6 +93,7 @@ impl Attrs { | |||
93 | } | 93 | } |
94 | 94 | ||
95 | pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool { | 95 | pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool { |
96 | // FIXME: handle cfg_attr :-) | ||
96 | self.by_key("cfg").tt_values().all(|tt| cfg_options.is_cfg_enabled(tt) != Some(false)) | 97 | self.by_key("cfg").tt_values().all(|tt| cfg_options.is_cfg_enabled(tt) != Some(false)) |
97 | } | 98 | } |
98 | } | 99 | } |
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index e09996c6f..eafaf48c1 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -9,11 +9,14 @@ use drop_bomb::DropBomb; | |||
9 | use either::Either; | 9 | use either::Either; |
10 | use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroDefId}; | 10 | use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroDefId}; |
11 | use ra_arena::{map::ArenaMap, Arena}; | 11 | use ra_arena::{map::ArenaMap, Arena}; |
12 | use ra_cfg::CfgOptions; | ||
13 | use ra_db::CrateId; | ||
12 | use ra_prof::profile; | 14 | use ra_prof::profile; |
13 | use ra_syntax::{ast, AstNode, AstPtr}; | 15 | use ra_syntax::{ast, AstNode, AstPtr}; |
14 | use rustc_hash::FxHashMap; | 16 | use rustc_hash::FxHashMap; |
15 | 17 | ||
16 | use crate::{ | 18 | use crate::{ |
19 | attr::Attrs, | ||
17 | db::DefDatabase, | 20 | db::DefDatabase, |
18 | expr::{Expr, ExprId, Pat, PatId}, | 21 | expr::{Expr, ExprId, Pat, PatId}, |
19 | item_scope::BuiltinShadowMode, | 22 | item_scope::BuiltinShadowMode, |
@@ -24,25 +27,59 @@ use crate::{ | |||
24 | AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, | 27 | AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, |
25 | }; | 28 | }; |
26 | 29 | ||
30 | /// A subser of Exander that only deals with cfg attributes. We only need it to | ||
31 | /// avoid cyclic queries in crate def map during enum processing. | ||
32 | pub(crate) struct CfgExpander { | ||
33 | cfg_options: CfgOptions, | ||
34 | hygiene: Hygiene, | ||
35 | } | ||
36 | |||
27 | pub(crate) struct Expander { | 37 | pub(crate) struct Expander { |
38 | cfg_expander: CfgExpander, | ||
28 | crate_def_map: Arc<CrateDefMap>, | 39 | crate_def_map: Arc<CrateDefMap>, |
29 | current_file_id: HirFileId, | 40 | current_file_id: HirFileId, |
30 | hygiene: Hygiene, | ||
31 | ast_id_map: Arc<AstIdMap>, | 41 | ast_id_map: Arc<AstIdMap>, |
32 | module: ModuleId, | 42 | module: ModuleId, |
33 | recursive_limit: usize, | 43 | recursive_limit: usize, |
34 | } | 44 | } |
35 | 45 | ||
46 | impl CfgExpander { | ||
47 | pub(crate) fn new( | ||
48 | db: &dyn DefDatabase, | ||
49 | current_file_id: HirFileId, | ||
50 | krate: CrateId, | ||
51 | ) -> CfgExpander { | ||
52 | let hygiene = Hygiene::new(db.upcast(), current_file_id); | ||
53 | let cfg_options = db.crate_graph()[krate].cfg_options.clone(); | ||
54 | CfgExpander { cfg_options, hygiene } | ||
55 | } | ||
56 | |||
57 | pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { | ||
58 | Attrs::new(owner, &self.hygiene) | ||
59 | } | ||
60 | |||
61 | pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { | ||
62 | attrs.is_cfg_enabled(&self.cfg_options) | ||
63 | } | ||
64 | } | ||
65 | |||
36 | impl Expander { | 66 | impl Expander { |
37 | pub(crate) fn new( | 67 | pub(crate) fn new( |
38 | db: &dyn DefDatabase, | 68 | db: &dyn DefDatabase, |
39 | current_file_id: HirFileId, | 69 | current_file_id: HirFileId, |
40 | module: ModuleId, | 70 | module: ModuleId, |
41 | ) -> Expander { | 71 | ) -> Expander { |
72 | let cfg_expander = CfgExpander::new(db, current_file_id, module.krate); | ||
42 | let crate_def_map = db.crate_def_map(module.krate); | 73 | let crate_def_map = db.crate_def_map(module.krate); |
43 | let hygiene = Hygiene::new(db.upcast(), current_file_id); | ||
44 | let ast_id_map = db.ast_id_map(current_file_id); | 74 | let ast_id_map = db.ast_id_map(current_file_id); |
45 | Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module, recursive_limit: 0 } | 75 | Expander { |
76 | cfg_expander, | ||
77 | crate_def_map, | ||
78 | current_file_id, | ||
79 | ast_id_map, | ||
80 | module, | ||
81 | recursive_limit: 0, | ||
82 | } | ||
46 | } | 83 | } |
47 | 84 | ||
48 | pub(crate) fn enter_expand<T: ast::AstNode>( | 85 | pub(crate) fn enter_expand<T: ast::AstNode>( |
@@ -75,7 +112,7 @@ impl Expander { | |||
75 | ast_id_map: mem::take(&mut self.ast_id_map), | 112 | ast_id_map: mem::take(&mut self.ast_id_map), |
76 | bomb: DropBomb::new("expansion mark dropped"), | 113 | bomb: DropBomb::new("expansion mark dropped"), |
77 | }; | 114 | }; |
78 | self.hygiene = Hygiene::new(db.upcast(), file_id); | 115 | self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id); |
79 | self.current_file_id = file_id; | 116 | self.current_file_id = file_id; |
80 | self.ast_id_map = db.ast_id_map(file_id); | 117 | self.ast_id_map = db.ast_id_map(file_id); |
81 | self.recursive_limit += 1; | 118 | self.recursive_limit += 1; |
@@ -91,7 +128,7 @@ impl Expander { | |||
91 | } | 128 | } |
92 | 129 | ||
93 | pub(crate) fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) { | 130 | pub(crate) fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) { |
94 | self.hygiene = Hygiene::new(db.upcast(), mark.file_id); | 131 | self.cfg_expander.hygiene = Hygiene::new(db.upcast(), mark.file_id); |
95 | self.current_file_id = mark.file_id; | 132 | self.current_file_id = mark.file_id; |
96 | self.ast_id_map = mem::take(&mut mark.ast_id_map); | 133 | self.ast_id_map = mem::take(&mut mark.ast_id_map); |
97 | self.recursive_limit -= 1; | 134 | self.recursive_limit -= 1; |
@@ -102,8 +139,16 @@ impl Expander { | |||
102 | InFile { file_id: self.current_file_id, value } | 139 | InFile { file_id: self.current_file_id, value } |
103 | } | 140 | } |
104 | 141 | ||
142 | pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { | ||
143 | self.cfg_expander.parse_attrs(owner) | ||
144 | } | ||
145 | |||
146 | pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { | ||
147 | self.cfg_expander.is_cfg_enabled(attrs) | ||
148 | } | ||
149 | |||
105 | fn parse_path(&mut self, path: ast::Path) -> Option<Path> { | 150 | fn parse_path(&mut self, path: ast::Path) -> Option<Path> { |
106 | Path::from_src(path, &self.hygiene) | 151 | Path::from_src(path, &self.cfg_expander.hygiene) |
107 | } | 152 | } |
108 | 153 | ||
109 | fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> { | 154 | fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> { |
@@ -142,7 +187,7 @@ pub struct Body { | |||
142 | pub item_scope: ItemScope, | 187 | pub item_scope: ItemScope, |
143 | } | 188 | } |
144 | 189 | ||
145 | pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>; | 190 | pub type ExprPtr = AstPtr<ast::Expr>; |
146 | pub type ExprSource = InFile<ExprPtr>; | 191 | pub type ExprSource = InFile<ExprPtr>; |
147 | 192 | ||
148 | pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>; | 193 | pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>; |
@@ -240,7 +285,7 @@ impl BodySourceMap { | |||
240 | } | 285 | } |
241 | 286 | ||
242 | pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprId> { | 287 | pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprId> { |
243 | let src = node.map(|it| Either::Left(AstPtr::new(it))); | 288 | let src = node.map(|it| AstPtr::new(it)); |
244 | self.expr_map.get(&src).cloned() | 289 | self.expr_map.get(&src).cloned() |
245 | } | 290 | } |
246 | 291 | ||
@@ -249,11 +294,6 @@ impl BodySourceMap { | |||
249 | self.expansions.get(&src).cloned() | 294 | self.expansions.get(&src).cloned() |
250 | } | 295 | } |
251 | 296 | ||
252 | pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option<ExprId> { | ||
253 | let src = node.map(|it| Either::Right(AstPtr::new(it))); | ||
254 | self.expr_map.get(&src).cloned() | ||
255 | } | ||
256 | |||
257 | pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> { | 297 | pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> { |
258 | self.pat_map_back[pat].clone() | 298 | self.pat_map_back[pat].clone() |
259 | } | 299 | } |
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 9d6ee095e..79abe55ce 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -2,9 +2,7 @@ | |||
2 | //! representation. | 2 | //! representation. |
3 | 3 | ||
4 | use either::Either; | 4 | use either::Either; |
5 | |||
6 | use hir_expand::{ | 5 | use hir_expand::{ |
7 | hygiene::Hygiene, | ||
8 | name::{name, AsName, Name}, | 6 | name::{name, AsName, Name}, |
9 | MacroDefId, MacroDefKind, | 7 | MacroDefId, MacroDefKind, |
10 | }; | 8 | }; |
@@ -18,10 +16,8 @@ use ra_syntax::{ | |||
18 | }; | 16 | }; |
19 | use test_utils::tested_by; | 17 | use test_utils::tested_by; |
20 | 18 | ||
21 | use super::{ExprSource, PatSource}; | ||
22 | use crate::{ | 19 | use crate::{ |
23 | adt::StructKind, | 20 | adt::StructKind, |
24 | attr::Attrs, | ||
25 | body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax}, | 21 | body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax}, |
26 | builtin_type::{BuiltinFloat, BuiltinInt}, | 22 | builtin_type::{BuiltinFloat, BuiltinInt}, |
27 | db::DefDatabase, | 23 | db::DefDatabase, |
@@ -31,12 +27,14 @@ use crate::{ | |||
31 | }, | 27 | }, |
32 | item_scope::BuiltinShadowMode, | 28 | item_scope::BuiltinShadowMode, |
33 | path::GenericArgs, | 29 | path::GenericArgs, |
34 | path::Path, | ||
35 | type_ref::{Mutability, TypeRef}, | 30 | type_ref::{Mutability, TypeRef}, |
36 | AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, HasModule, Intern, | 31 | AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, |
37 | ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, | 32 | StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, |
38 | }; | 33 | }; |
39 | 34 | ||
35 | use super::{ExprSource, PatSource}; | ||
36 | use ast::AstChildren; | ||
37 | |||
40 | pub(super) fn lower( | 38 | pub(super) fn lower( |
41 | db: &dyn DefDatabase, | 39 | db: &dyn DefDatabase, |
42 | def: DefWithBodyId, | 40 | def: DefWithBodyId, |
@@ -104,7 +102,6 @@ impl ExprCollector<'_> { | |||
104 | } | 102 | } |
105 | 103 | ||
106 | fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { | 104 | fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { |
107 | let ptr = Either::Left(ptr); | ||
108 | let src = self.expander.to_source(ptr); | 105 | let src = self.expander.to_source(ptr); |
109 | let id = self.make_expr(expr, Ok(src.clone())); | 106 | let id = self.make_expr(expr, Ok(src.clone())); |
110 | self.source_map.expr_map.insert(src, id); | 107 | self.source_map.expr_map.insert(src, id); |
@@ -115,13 +112,6 @@ impl ExprCollector<'_> { | |||
115 | fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId { | 112 | fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId { |
116 | self.make_expr(expr, Err(SyntheticSyntax)) | 113 | self.make_expr(expr, Err(SyntheticSyntax)) |
117 | } | 114 | } |
118 | fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr<ast::RecordField>) -> ExprId { | ||
119 | let ptr = Either::Right(ptr); | ||
120 | let src = self.expander.to_source(ptr); | ||
121 | let id = self.make_expr(expr, Ok(src.clone())); | ||
122 | self.source_map.expr_map.insert(src, id); | ||
123 | id | ||
124 | } | ||
125 | fn empty_block(&mut self) -> ExprId { | 115 | fn empty_block(&mut self) -> ExprId { |
126 | self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None }) | 116 | self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None }) |
127 | } | 117 | } |
@@ -291,7 +281,7 @@ impl ExprCollector<'_> { | |||
291 | ast::Expr::ParenExpr(e) => { | 281 | ast::Expr::ParenExpr(e) => { |
292 | let inner = self.collect_expr_opt(e.expr()); | 282 | let inner = self.collect_expr_opt(e.expr()); |
293 | // make the paren expr point to the inner expression as well | 283 | // make the paren expr point to the inner expression as well |
294 | let src = self.expander.to_source(Either::Left(syntax_ptr)); | 284 | let src = self.expander.to_source(syntax_ptr); |
295 | self.source_map.expr_map.insert(src, inner); | 285 | self.source_map.expr_map.insert(src, inner); |
296 | inner | 286 | inner |
297 | } | 287 | } |
@@ -300,7 +290,6 @@ impl ExprCollector<'_> { | |||
300 | self.alloc_expr(Expr::Return { expr }, syntax_ptr) | 290 | self.alloc_expr(Expr::Return { expr }, syntax_ptr) |
301 | } | 291 | } |
302 | ast::Expr::RecordLit(e) => { | 292 | ast::Expr::RecordLit(e) => { |
303 | let crate_graph = self.db.crate_graph(); | ||
304 | let path = e.path().and_then(|path| self.expander.parse_path(path)); | 293 | let path = e.path().and_then(|path| self.expander.parse_path(path)); |
305 | let mut field_ptrs = Vec::new(); | 294 | let mut field_ptrs = Vec::new(); |
306 | let record_lit = if let Some(nfl) = e.record_field_list() { | 295 | let record_lit = if let Some(nfl) = e.record_field_list() { |
@@ -308,31 +297,17 @@ impl ExprCollector<'_> { | |||
308 | .fields() | 297 | .fields() |
309 | .inspect(|field| field_ptrs.push(AstPtr::new(field))) | 298 | .inspect(|field| field_ptrs.push(AstPtr::new(field))) |
310 | .filter_map(|field| { | 299 | .filter_map(|field| { |
311 | let module_id = ContainerId::DefWithBodyId(self.def).module(self.db); | 300 | let attrs = self.expander.parse_attrs(&field); |
312 | let attrs = Attrs::new( | 301 | if !self.expander.is_cfg_enabled(&attrs) { |
313 | &field, | ||
314 | &Hygiene::new(self.db.upcast(), self.expander.current_file_id), | ||
315 | ); | ||
316 | |||
317 | if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) { | ||
318 | return None; | 302 | return None; |
319 | } | 303 | } |
304 | let name = field.field_name()?.as_name(); | ||
320 | 305 | ||
321 | Some(RecordLitField { | 306 | Some(RecordLitField { |
322 | name: field | 307 | name, |
323 | .name_ref() | 308 | expr: match field.expr() { |
324 | .map(|nr| nr.as_name()) | 309 | Some(e) => self.collect_expr(e), |
325 | .unwrap_or_else(Name::missing), | 310 | None => self.missing_expr(), |
326 | expr: if let Some(e) = field.expr() { | ||
327 | self.collect_expr(e) | ||
328 | } else if let Some(nr) = field.name_ref() { | ||
329 | // field shorthand | ||
330 | self.alloc_expr_field_shorthand( | ||
331 | Expr::Path(Path::from_name_ref(&nr)), | ||
332 | AstPtr::new(&field), | ||
333 | ) | ||
334 | } else { | ||
335 | self.missing_expr() | ||
336 | }, | 311 | }, |
337 | }) | 312 | }) |
338 | }) | 313 | }) |
@@ -624,8 +599,8 @@ impl ExprCollector<'_> { | |||
624 | } | 599 | } |
625 | ast::Pat::TupleStructPat(p) => { | 600 | ast::Pat::TupleStructPat(p) => { |
626 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 601 | let path = p.path().and_then(|path| self.expander.parse_path(path)); |
627 | let args = p.args().map(|p| self.collect_pat(p)).collect(); | 602 | let (args, ellipsis) = self.collect_tuple_pat(p.args()); |
628 | Pat::TupleStruct { path, args } | 603 | Pat::TupleStruct { path, args, ellipsis } |
629 | } | 604 | } |
630 | ast::Pat::RefPat(p) => { | 605 | ast::Pat::RefPat(p) => { |
631 | let pat = self.collect_pat_opt(p.pat()); | 606 | let pat = self.collect_pat_opt(p.pat()); |
@@ -642,10 +617,10 @@ impl ExprCollector<'_> { | |||
642 | } | 617 | } |
643 | ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()), | 618 | ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()), |
644 | ast::Pat::TuplePat(p) => { | 619 | ast::Pat::TuplePat(p) => { |
645 | let args = p.args().map(|p| self.collect_pat(p)).collect(); | 620 | let (args, ellipsis) = self.collect_tuple_pat(p.args()); |
646 | Pat::Tuple(args) | 621 | Pat::Tuple { args, ellipsis } |
647 | } | 622 | } |
648 | ast::Pat::PlaceholderPat(_) | ast::Pat::DotDotPat(_) => Pat::Wild, | 623 | ast::Pat::PlaceholderPat(_) => Pat::Wild, |
649 | ast::Pat::RecordPat(p) => { | 624 | ast::Pat::RecordPat(p) => { |
650 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 625 | let path = p.path().and_then(|path| self.expander.parse_path(path)); |
651 | let record_field_pat_list = | 626 | let record_field_pat_list = |
@@ -663,7 +638,7 @@ impl ExprCollector<'_> { | |||
663 | let iter = record_field_pat_list.record_field_pats().filter_map(|f| { | 638 | let iter = record_field_pat_list.record_field_pats().filter_map(|f| { |
664 | let ast_pat = f.pat()?; | 639 | let ast_pat = f.pat()?; |
665 | let pat = self.collect_pat(ast_pat); | 640 | let pat = self.collect_pat(ast_pat); |
666 | let name = f.name()?.as_name(); | 641 | let name = f.field_name()?.as_name(); |
667 | Some(RecordFieldPat { name, pat }) | 642 | Some(RecordFieldPat { name, pat }) |
668 | }); | 643 | }); |
669 | fields.extend(iter); | 644 | fields.extend(iter); |
@@ -691,7 +666,9 @@ impl ExprCollector<'_> { | |||
691 | Pat::Missing | 666 | Pat::Missing |
692 | } | 667 | } |
693 | } | 668 | } |
694 | 669 | ast::Pat::DotDotPat(_) => unreachable!( | |
670 | "`DotDotPat` requires special handling and should not be mapped to a Pat." | ||
671 | ), | ||
695 | // FIXME: implement | 672 | // FIXME: implement |
696 | ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, | 673 | ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, |
697 | }; | 674 | }; |
@@ -706,6 +683,19 @@ impl ExprCollector<'_> { | |||
706 | self.missing_pat() | 683 | self.missing_pat() |
707 | } | 684 | } |
708 | } | 685 | } |
686 | |||
687 | fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Vec<PatId>, Option<usize>) { | ||
688 | // Find the location of the `..`, if there is one. Note that we do not | ||
689 | // consider the possiblity of there being multiple `..` here. | ||
690 | let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::DotDotPat(_))); | ||
691 | // We want to skip the `..` pattern here, since we account for it above. | ||
692 | let args = args | ||
693 | .filter(|p| !matches!(p, ast::Pat::DotDotPat(_))) | ||
694 | .map(|p| self.collect_pat(p)) | ||
695 | .collect(); | ||
696 | |||
697 | (args, ellipsis) | ||
698 | } | ||
709 | } | 699 | } |
710 | 700 | ||
711 | impl From<ast::BinOp> for BinaryOp { | 701 | impl From<ast::BinOp> for BinaryOp { |
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index b8fbf0ed4..ccb682f9a 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -9,18 +9,19 @@ use hir_expand::{ | |||
9 | }; | 9 | }; |
10 | use ra_prof::profile; | 10 | use ra_prof::profile; |
11 | use ra_syntax::ast::{ | 11 | use ra_syntax::ast::{ |
12 | self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, VisibilityOwner, | 12 | self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, TypeBoundsOwner, |
13 | VisibilityOwner, | ||
13 | }; | 14 | }; |
14 | 15 | ||
15 | use crate::{ | 16 | use crate::{ |
16 | attr::Attrs, | 17 | attr::Attrs, |
17 | db::DefDatabase, | 18 | db::DefDatabase, |
18 | path::{path, GenericArgs, Path}, | 19 | path::{path, AssociatedTypeBinding, GenericArgs, Path}, |
19 | src::HasSource, | 20 | src::HasSource, |
20 | type_ref::{Mutability, TypeBound, TypeRef}, | 21 | type_ref::{Mutability, TypeBound, TypeRef}, |
21 | visibility::RawVisibility, | 22 | visibility::RawVisibility, |
22 | AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, | 23 | AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, |
23 | ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, | 24 | ImplId, Intern, Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc, |
24 | }; | 25 | }; |
25 | 26 | ||
26 | #[derive(Debug, Clone, PartialEq, Eq)] | 27 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -95,7 +96,11 @@ fn desugar_future_path(orig: TypeRef) -> Path { | |||
95 | let path = path![std::future::Future]; | 96 | let path = path![std::future::Future]; |
96 | let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect(); | 97 | let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect(); |
97 | let mut last = GenericArgs::empty(); | 98 | let mut last = GenericArgs::empty(); |
98 | last.bindings.push((name![Output], orig)); | 99 | last.bindings.push(AssociatedTypeBinding { |
100 | name: name![Output], | ||
101 | type_ref: Some(orig), | ||
102 | bounds: Vec::new(), | ||
103 | }); | ||
99 | generic_args.push(Some(Arc::new(last))); | 104 | generic_args.push(Some(Arc::new(last))); |
100 | 105 | ||
101 | Path::from_known_path(path, generic_args) | 106 | Path::from_known_path(path, generic_args) |
@@ -106,6 +111,7 @@ pub struct TypeAliasData { | |||
106 | pub name: Name, | 111 | pub name: Name, |
107 | pub type_ref: Option<TypeRef>, | 112 | pub type_ref: Option<TypeRef>, |
108 | pub visibility: RawVisibility, | 113 | pub visibility: RawVisibility, |
114 | pub bounds: Vec<TypeBound>, | ||
109 | } | 115 | } |
110 | 116 | ||
111 | impl TypeAliasData { | 117 | impl TypeAliasData { |
@@ -118,9 +124,17 @@ impl TypeAliasData { | |||
118 | let name = node.value.name().map_or_else(Name::missing, |n| n.as_name()); | 124 | let name = node.value.name().map_or_else(Name::missing, |n| n.as_name()); |
119 | let type_ref = node.value.type_ref().map(TypeRef::from_ast); | 125 | let type_ref = node.value.type_ref().map(TypeRef::from_ast); |
120 | let vis_default = RawVisibility::default_for_container(loc.container); | 126 | let vis_default = RawVisibility::default_for_container(loc.container); |
121 | let visibility = | 127 | let visibility = RawVisibility::from_ast_with_default( |
122 | RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility())); | 128 | db, |
123 | Arc::new(TypeAliasData { name, type_ref, visibility }) | 129 | vis_default, |
130 | node.as_ref().map(|n| n.visibility()), | ||
131 | ); | ||
132 | let bounds = if let Some(bound_list) = node.value.type_bound_list() { | ||
133 | bound_list.bounds().map(TypeBound::from_ast).collect() | ||
134 | } else { | ||
135 | Vec::new() | ||
136 | }; | ||
137 | Arc::new(TypeAliasData { name, type_ref, visibility, bounds }) | ||
124 | } | 138 | } |
125 | } | 139 | } |
126 | 140 | ||
@@ -218,10 +232,17 @@ impl ImplData { | |||
218 | let mut items = Vec::new(); | 232 | let mut items = Vec::new(); |
219 | 233 | ||
220 | if let Some(item_list) = src.value.item_list() { | 234 | if let Some(item_list) = src.value.item_list() { |
221 | items.extend(collect_impl_items(db, item_list.impl_items(), src.file_id, id)); | 235 | let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); |
236 | items.extend(collect_impl_items( | ||
237 | db, | ||
238 | &mut expander, | ||
239 | item_list.impl_items(), | ||
240 | src.file_id, | ||
241 | id, | ||
242 | )); | ||
222 | items.extend(collect_impl_items_in_macros( | 243 | items.extend(collect_impl_items_in_macros( |
223 | db, | 244 | db, |
224 | module_id, | 245 | &mut expander, |
225 | &src.with_value(item_list), | 246 | &src.with_value(item_list), |
226 | id, | 247 | id, |
227 | )); | 248 | )); |
@@ -268,18 +289,17 @@ impl ConstData { | |||
268 | 289 | ||
269 | fn collect_impl_items_in_macros( | 290 | fn collect_impl_items_in_macros( |
270 | db: &dyn DefDatabase, | 291 | db: &dyn DefDatabase, |
271 | module_id: ModuleId, | 292 | expander: &mut Expander, |
272 | impl_def: &InFile<ast::ItemList>, | 293 | impl_def: &InFile<ast::ItemList>, |
273 | id: ImplId, | 294 | id: ImplId, |
274 | ) -> Vec<AssocItemId> { | 295 | ) -> Vec<AssocItemId> { |
275 | let mut expander = Expander::new(db, impl_def.file_id, module_id); | ||
276 | let mut res = Vec::new(); | 296 | let mut res = Vec::new(); |
277 | 297 | ||
278 | // We set a limit to protect against infinite recursion | 298 | // We set a limit to protect against infinite recursion |
279 | let limit = 100; | 299 | let limit = 100; |
280 | 300 | ||
281 | for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { | 301 | for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { |
282 | res.extend(collect_impl_items_in_macro(db, &mut expander, m, id, limit)) | 302 | res.extend(collect_impl_items_in_macro(db, expander, m, id, limit)) |
283 | } | 303 | } |
284 | 304 | ||
285 | res | 305 | res |
@@ -300,6 +320,7 @@ fn collect_impl_items_in_macro( | |||
300 | let items: InFile<ast::MacroItems> = expander.to_source(items); | 320 | let items: InFile<ast::MacroItems> = expander.to_source(items); |
301 | let mut res = collect_impl_items( | 321 | let mut res = collect_impl_items( |
302 | db, | 322 | db, |
323 | expander, | ||
303 | items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), | 324 | items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), |
304 | items.file_id, | 325 | items.file_id, |
305 | id, | 326 | id, |
@@ -319,32 +340,26 @@ fn collect_impl_items_in_macro( | |||
319 | 340 | ||
320 | fn collect_impl_items( | 341 | fn collect_impl_items( |
321 | db: &dyn DefDatabase, | 342 | db: &dyn DefDatabase, |
343 | expander: &mut Expander, | ||
322 | impl_items: impl Iterator<Item = ImplItem>, | 344 | impl_items: impl Iterator<Item = ImplItem>, |
323 | file_id: crate::HirFileId, | 345 | file_id: crate::HirFileId, |
324 | id: ImplId, | 346 | id: ImplId, |
325 | ) -> Vec<AssocItemId> { | 347 | ) -> Vec<AssocItemId> { |
326 | let items = db.ast_id_map(file_id); | 348 | let items = db.ast_id_map(file_id); |
327 | let crate_graph = db.crate_graph(); | ||
328 | let module_id = id.lookup(db).container.module(db); | ||
329 | 349 | ||
330 | impl_items | 350 | impl_items |
331 | .filter_map(|item_node| match item_node { | 351 | .filter_map(|item_node| match item_node { |
332 | ast::ImplItem::FnDef(it) => { | 352 | ast::ImplItem::FnDef(it) => { |
353 | let attrs = expander.parse_attrs(&it); | ||
354 | if !expander.is_cfg_enabled(&attrs) { | ||
355 | return None; | ||
356 | } | ||
333 | let def = FunctionLoc { | 357 | let def = FunctionLoc { |
334 | container: AssocContainerId::ImplId(id), | 358 | container: AssocContainerId::ImplId(id), |
335 | ast_id: AstId::new(file_id, items.ast_id(&it)), | 359 | ast_id: AstId::new(file_id, items.ast_id(&it)), |
336 | } | 360 | } |
337 | .intern(db); | 361 | .intern(db); |
338 | 362 | Some(def.into()) | |
339 | if !db | ||
340 | .function_data(def) | ||
341 | .attrs | ||
342 | .is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) | ||
343 | { | ||
344 | None | ||
345 | } else { | ||
346 | Some(def.into()) | ||
347 | } | ||
348 | } | 363 | } |
349 | ast::ImplItem::ConstDef(it) => { | 364 | ast::ImplItem::ConstDef(it) => { |
350 | let def = ConstLoc { | 365 | let def = ConstLoc { |
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs index e11bdf3ec..a0cdad529 100644 --- a/crates/ra_hir_def/src/expr.rs +++ b/crates/ra_hir_def/src/expr.rs | |||
@@ -374,7 +374,7 @@ pub struct RecordFieldPat { | |||
374 | pub enum Pat { | 374 | pub enum Pat { |
375 | Missing, | 375 | Missing, |
376 | Wild, | 376 | Wild, |
377 | Tuple(Vec<PatId>), | 377 | Tuple { args: Vec<PatId>, ellipsis: Option<usize> }, |
378 | Or(Vec<PatId>), | 378 | Or(Vec<PatId>), |
379 | Record { path: Option<Path>, args: Vec<RecordFieldPat>, ellipsis: bool }, | 379 | Record { path: Option<Path>, args: Vec<RecordFieldPat>, ellipsis: bool }, |
380 | Range { start: ExprId, end: ExprId }, | 380 | Range { start: ExprId, end: ExprId }, |
@@ -382,7 +382,7 @@ pub enum Pat { | |||
382 | Path(Path), | 382 | Path(Path), |
383 | Lit(ExprId), | 383 | Lit(ExprId), |
384 | Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> }, | 384 | Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> }, |
385 | TupleStruct { path: Option<Path>, args: Vec<PatId> }, | 385 | TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> }, |
386 | Ref { pat: PatId, mutability: Mutability }, | 386 | Ref { pat: PatId, mutability: Mutability }, |
387 | } | 387 | } |
388 | 388 | ||
@@ -393,7 +393,7 @@ impl Pat { | |||
393 | Pat::Bind { subpat, .. } => { | 393 | Pat::Bind { subpat, .. } => { |
394 | subpat.iter().copied().for_each(f); | 394 | subpat.iter().copied().for_each(f); |
395 | } | 395 | } |
396 | Pat::Or(args) | Pat::Tuple(args) | Pat::TupleStruct { args, .. } => { | 396 | Pat::Or(args) | Pat::Tuple { args, .. } | Pat::TupleStruct { args, .. } => { |
397 | args.iter().copied().for_each(f); | 397 | args.iter().copied().for_each(f); |
398 | } | 398 | } |
399 | Pat::Ref { pat, .. } => f(*pat), | 399 | Pat::Ref { pat, .. } => f(*pat), |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 8fe3f8617..98c74fe25 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -462,6 +462,14 @@ impl DefCollector<'_> { | |||
462 | Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => { | 462 | Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => { |
463 | tested_by!(glob_enum); | 463 | tested_by!(glob_enum); |
464 | // glob import from enum => just import all the variants | 464 | // glob import from enum => just import all the variants |
465 | |||
466 | // XXX: urgh, so this works by accident! Here, we look at | ||
467 | // the enum data, and, in theory, this might require us to | ||
468 | // look back at the crate_def_map, creating a cycle. For | ||
469 | // example, `enum E { crate::some_macro!(); }`. Luckely, the | ||
470 | // only kind of macro that is allowed inside enum is a | ||
471 | // `cfg_macro`, and we don't need to run name resolution for | ||
472 | // it, but this is sheer luck! | ||
465 | let enum_data = self.db.enum_data(e); | 473 | let enum_data = self.db.enum_data(e); |
466 | let resolutions = enum_data | 474 | let resolutions = enum_data |
467 | .variants | 475 | .variants |
@@ -977,11 +985,7 @@ impl ModCollector<'_, '_> { | |||
977 | } | 985 | } |
978 | 986 | ||
979 | fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { | 987 | fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { |
980 | // FIXME: handle cfg_attr :-) | 988 | attrs.is_cfg_enabled(self.def_collector.cfg_options) |
981 | attrs | ||
982 | .by_key("cfg") | ||
983 | .tt_values() | ||
984 | .all(|tt| self.def_collector.cfg_options.is_cfg_enabled(tt) != Some(false)) | ||
985 | } | 989 | } |
986 | } | 990 | } |
987 | 991 | ||
diff --git a/crates/ra_hir_def/src/nameres/tests/incremental.rs b/crates/ra_hir_def/src/nameres/tests/incremental.rs index 496fc6b08..87165ac33 100644 --- a/crates/ra_hir_def/src/nameres/tests/incremental.rs +++ b/crates/ra_hir_def/src/nameres/tests/incremental.rs | |||
@@ -32,6 +32,9 @@ fn typing_inside_a_function_should_not_invalidate_def_map() { | |||
32 | 32 | ||
33 | use crate::foo::bar::Baz; | 33 | use crate::foo::bar::Baz; |
34 | 34 | ||
35 | enum E { A, B } | ||
36 | use E::*; | ||
37 | |||
35 | fn foo() -> i32 { | 38 | fn foo() -> i32 { |
36 | 1 + 1 | 39 | 1 + 1 |
37 | } | 40 | } |
@@ -46,6 +49,9 @@ fn typing_inside_a_function_should_not_invalidate_def_map() { | |||
46 | 49 | ||
47 | use crate::foo::bar::Baz; | 50 | use crate::foo::bar::Baz; |
48 | 51 | ||
52 | enum E { A, B } | ||
53 | use E::*; | ||
54 | |||
49 | fn foo() -> i32 { 92 } | 55 | fn foo() -> i32 { 92 } |
50 | ", | 56 | ", |
51 | ); | 57 | ); |
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 904080341..162b3c8c7 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs | |||
@@ -14,7 +14,10 @@ use hir_expand::{ | |||
14 | use ra_db::CrateId; | 14 | use ra_db::CrateId; |
15 | use ra_syntax::ast; | 15 | use ra_syntax::ast; |
16 | 16 | ||
17 | use crate::{type_ref::TypeRef, InFile}; | 17 | use crate::{ |
18 | type_ref::{TypeBound, TypeRef}, | ||
19 | InFile, | ||
20 | }; | ||
18 | 21 | ||
19 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] | 22 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] |
20 | pub struct ModPath { | 23 | pub struct ModPath { |
@@ -111,7 +114,21 @@ pub struct GenericArgs { | |||
111 | /// is left out. | 114 | /// is left out. |
112 | pub has_self_type: bool, | 115 | pub has_self_type: bool, |
113 | /// Associated type bindings like in `Iterator<Item = T>`. | 116 | /// Associated type bindings like in `Iterator<Item = T>`. |
114 | pub bindings: Vec<(Name, TypeRef)>, | 117 | pub bindings: Vec<AssociatedTypeBinding>, |
118 | } | ||
119 | |||
120 | /// An associated type binding like in `Iterator<Item = T>`. | ||
121 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
122 | pub struct AssociatedTypeBinding { | ||
123 | /// The name of the associated type. | ||
124 | pub name: Name, | ||
125 | /// The type bound to this associated type (in `Item = T`, this would be the | ||
126 | /// `T`). This can be `None` if there are bounds instead. | ||
127 | pub type_ref: Option<TypeRef>, | ||
128 | /// Bounds for the associated type, like in `Iterator<Item: | ||
129 | /// SomeOtherTrait>`. (This is the unstable `associated_type_bounds` | ||
130 | /// feature.) | ||
131 | pub bounds: Vec<TypeBound>, | ||
115 | } | 132 | } |
116 | 133 | ||
117 | /// A single generic argument. | 134 | /// A single generic argument. |
@@ -134,11 +151,6 @@ impl Path { | |||
134 | lower::lower_path(path, hygiene) | 151 | lower::lower_path(path, hygiene) |
135 | } | 152 | } |
136 | 153 | ||
137 | /// Converts an `ast::NameRef` into a single-identifier `Path`. | ||
138 | pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path { | ||
139 | Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] } | ||
140 | } | ||
141 | |||
142 | /// Converts a known mod path to `Path`. | 154 | /// Converts a known mod path to `Path`. |
143 | pub(crate) fn from_known_path( | 155 | pub(crate) fn from_known_path( |
144 | path: ModPath, | 156 | path: ModPath, |
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs index 0f806d6fb..9ec2e0dcd 100644 --- a/crates/ra_hir_def/src/path/lower.rs +++ b/crates/ra_hir_def/src/path/lower.rs | |||
@@ -9,11 +9,12 @@ use hir_expand::{ | |||
9 | hygiene::Hygiene, | 9 | hygiene::Hygiene, |
10 | name::{name, AsName}, | 10 | name::{name, AsName}, |
11 | }; | 11 | }; |
12 | use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner}; | 12 | use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner, TypeBoundsOwner}; |
13 | 13 | ||
14 | use super::AssociatedTypeBinding; | ||
14 | use crate::{ | 15 | use crate::{ |
15 | path::{GenericArg, GenericArgs, ModPath, Path, PathKind}, | 16 | path::{GenericArg, GenericArgs, ModPath, Path, PathKind}, |
16 | type_ref::TypeRef, | 17 | type_ref::{TypeBound, TypeRef}, |
17 | }; | 18 | }; |
18 | 19 | ||
19 | pub(super) use lower_use::lower_use_tree; | 20 | pub(super) use lower_use::lower_use_tree; |
@@ -136,10 +137,16 @@ pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs> | |||
136 | // lifetimes ignored for now | 137 | // lifetimes ignored for now |
137 | let mut bindings = Vec::new(); | 138 | let mut bindings = Vec::new(); |
138 | for assoc_type_arg in node.assoc_type_args() { | 139 | for assoc_type_arg in node.assoc_type_args() { |
140 | let assoc_type_arg: ast::AssocTypeArg = assoc_type_arg; | ||
139 | if let Some(name_ref) = assoc_type_arg.name_ref() { | 141 | if let Some(name_ref) = assoc_type_arg.name_ref() { |
140 | let name = name_ref.as_name(); | 142 | let name = name_ref.as_name(); |
141 | let type_ref = TypeRef::from_ast_opt(assoc_type_arg.type_ref()); | 143 | let type_ref = assoc_type_arg.type_ref().map(TypeRef::from_ast); |
142 | bindings.push((name, type_ref)); | 144 | let bounds = if let Some(l) = assoc_type_arg.type_bound_list() { |
145 | l.bounds().map(TypeBound::from_ast).collect() | ||
146 | } else { | ||
147 | Vec::new() | ||
148 | }; | ||
149 | bindings.push(AssociatedTypeBinding { name, type_ref, bounds }); | ||
143 | } | 150 | } |
144 | } | 151 | } |
145 | if args.is_empty() && bindings.is_empty() { | 152 | if args.is_empty() && bindings.is_empty() { |
@@ -168,7 +175,11 @@ fn lower_generic_args_from_fn_path( | |||
168 | } | 175 | } |
169 | if let Some(ret_type) = ret_type { | 176 | if let Some(ret_type) = ret_type { |
170 | let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); | 177 | let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); |
171 | bindings.push((name![Output], type_ref)) | 178 | bindings.push(AssociatedTypeBinding { |
179 | name: name![Output], | ||
180 | type_ref: Some(type_ref), | ||
181 | bounds: Vec::new(), | ||
182 | }); | ||
172 | } | 183 | } |
173 | if args.is_empty() && bindings.is_empty() { | 184 | if args.is_empty() && bindings.is_empty() { |
174 | None | 185 | None |
diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs index ea29c4176..f308c6bdf 100644 --- a/crates/ra_hir_def/src/type_ref.rs +++ b/crates/ra_hir_def/src/type_ref.rs | |||
@@ -163,8 +163,16 @@ impl TypeRef { | |||
163 | let crate::path::GenericArg::Type(type_ref) = arg; | 163 | let crate::path::GenericArg::Type(type_ref) = arg; |
164 | go(type_ref, f); | 164 | go(type_ref, f); |
165 | } | 165 | } |
166 | for (_, type_ref) in &args_and_bindings.bindings { | 166 | for binding in &args_and_bindings.bindings { |
167 | go(type_ref, f); | 167 | if let Some(type_ref) = &binding.type_ref { |
168 | go(type_ref, f); | ||
169 | } | ||
170 | for bound in &binding.bounds { | ||
171 | match bound { | ||
172 | TypeBound::Path(path) => go_path(path, f), | ||
173 | TypeBound::Error => (), | ||
174 | } | ||
175 | } | ||
168 | } | 176 | } |
169 | } | 177 | } |
170 | } | 178 | } |