diff options
26 files changed, 271 insertions, 140 deletions
diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs index e466c9a86..e47feda71 100644 --- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs | |||
@@ -10,7 +10,7 @@ use ra_syntax::{ | |||
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}, | 12 | ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}, |
13 | utils::{get_missing_impl_items, resolve_target_trait}, | 13 | utils::{get_missing_assoc_items, resolve_target_trait}, |
14 | Assist, AssistCtx, AssistId, | 14 | Assist, AssistCtx, AssistId, |
15 | }; | 15 | }; |
16 | 16 | ||
@@ -112,25 +112,25 @@ fn add_missing_impl_members_inner( | |||
112 | 112 | ||
113 | let trait_ = resolve_target_trait(&ctx.sema, &impl_node)?; | 113 | let trait_ = resolve_target_trait(&ctx.sema, &impl_node)?; |
114 | 114 | ||
115 | let def_name = |item: &ast::ImplItem| -> Option<SmolStr> { | 115 | let def_name = |item: &ast::AssocItem| -> Option<SmolStr> { |
116 | match item { | 116 | match item { |
117 | ast::ImplItem::FnDef(def) => def.name(), | 117 | ast::AssocItem::FnDef(def) => def.name(), |
118 | ast::ImplItem::TypeAliasDef(def) => def.name(), | 118 | ast::AssocItem::TypeAliasDef(def) => def.name(), |
119 | ast::ImplItem::ConstDef(def) => def.name(), | 119 | ast::AssocItem::ConstDef(def) => def.name(), |
120 | } | 120 | } |
121 | .map(|it| it.text().clone()) | 121 | .map(|it| it.text().clone()) |
122 | }; | 122 | }; |
123 | 123 | ||
124 | let missing_items = get_missing_impl_items(&ctx.sema, &impl_node) | 124 | let missing_items = get_missing_assoc_items(&ctx.sema, &impl_node) |
125 | .iter() | 125 | .iter() |
126 | .map(|i| match i { | 126 | .map(|i| match i { |
127 | hir::AssocItem::Function(i) => ast::ImplItem::FnDef(i.source(ctx.db).value), | 127 | hir::AssocItem::Function(i) => ast::AssocItem::FnDef(i.source(ctx.db).value), |
128 | hir::AssocItem::TypeAlias(i) => ast::ImplItem::TypeAliasDef(i.source(ctx.db).value), | 128 | hir::AssocItem::TypeAlias(i) => ast::AssocItem::TypeAliasDef(i.source(ctx.db).value), |
129 | hir::AssocItem::Const(i) => ast::ImplItem::ConstDef(i.source(ctx.db).value), | 129 | hir::AssocItem::Const(i) => ast::AssocItem::ConstDef(i.source(ctx.db).value), |
130 | }) | 130 | }) |
131 | .filter(|t| def_name(&t).is_some()) | 131 | .filter(|t| def_name(&t).is_some()) |
132 | .filter(|t| match t { | 132 | .filter(|t| match t { |
133 | ast::ImplItem::FnDef(def) => match mode { | 133 | ast::AssocItem::FnDef(def) => match mode { |
134 | AddMissingImplMembersMode::DefaultMethodsOnly => def.body().is_some(), | 134 | AddMissingImplMembersMode::DefaultMethodsOnly => def.body().is_some(), |
135 | AddMissingImplMembersMode::NoDefaultMethods => def.body().is_none(), | 135 | AddMissingImplMembersMode::NoDefaultMethods => def.body().is_none(), |
136 | }, | 136 | }, |
@@ -145,7 +145,7 @@ fn add_missing_impl_members_inner( | |||
145 | let sema = ctx.sema; | 145 | let sema = ctx.sema; |
146 | 146 | ||
147 | ctx.add_assist(AssistId(assist_id), label, |edit| { | 147 | ctx.add_assist(AssistId(assist_id), label, |edit| { |
148 | let n_existing_items = impl_item_list.impl_items().count(); | 148 | let n_existing_items = impl_item_list.assoc_items().count(); |
149 | let source_scope = sema.scope_for_def(trait_); | 149 | let source_scope = sema.scope_for_def(trait_); |
150 | let target_scope = sema.scope(impl_item_list.syntax()); | 150 | let target_scope = sema.scope(impl_item_list.syntax()); |
151 | let ast_transform = QualifyPaths::new(&target_scope, &source_scope) | 151 | let ast_transform = QualifyPaths::new(&target_scope, &source_scope) |
@@ -154,13 +154,13 @@ fn add_missing_impl_members_inner( | |||
154 | .into_iter() | 154 | .into_iter() |
155 | .map(|it| ast_transform::apply(&*ast_transform, it)) | 155 | .map(|it| ast_transform::apply(&*ast_transform, it)) |
156 | .map(|it| match it { | 156 | .map(|it| match it { |
157 | ast::ImplItem::FnDef(def) => ast::ImplItem::FnDef(add_body(def)), | 157 | ast::AssocItem::FnDef(def) => ast::AssocItem::FnDef(add_body(def)), |
158 | _ => it, | 158 | _ => it, |
159 | }) | 159 | }) |
160 | .map(|it| edit::remove_attrs_and_docs(&it)); | 160 | .map(|it| edit::remove_attrs_and_docs(&it)); |
161 | let new_impl_item_list = impl_item_list.append_items(items); | 161 | let new_impl_item_list = impl_item_list.append_items(items); |
162 | let cursor_position = { | 162 | let cursor_position = { |
163 | let first_new_item = new_impl_item_list.impl_items().nth(n_existing_items).unwrap(); | 163 | let first_new_item = new_impl_item_list.assoc_items().nth(n_existing_items).unwrap(); |
164 | first_new_item.syntax().text_range().start() | 164 | first_new_item.syntax().text_range().start() |
165 | }; | 165 | }; |
166 | 166 | ||
diff --git a/crates/ra_assists/src/handlers/add_new.rs b/crates/ra_assists/src/handlers/add_new.rs index 0f9174a29..e8a36c7de 100644 --- a/crates/ra_assists/src/handlers/add_new.rs +++ b/crates/ra_assists/src/handlers/add_new.rs | |||
@@ -162,8 +162,8 @@ fn find_struct_impl(ctx: &AssistCtx, strukt: &ast::StructDef) -> Option<Option<a | |||
162 | 162 | ||
163 | fn has_new_fn(imp: &ast::ImplDef) -> bool { | 163 | fn has_new_fn(imp: &ast::ImplDef) -> bool { |
164 | if let Some(il) = imp.item_list() { | 164 | if let Some(il) = imp.item_list() { |
165 | for item in il.impl_items() { | 165 | for item in il.assoc_items() { |
166 | if let ast::ImplItem::FnDef(f) = item { | 166 | if let ast::AssocItem::FnDef(f) = item { |
167 | if let Some(name) = f.name() { | 167 | if let Some(name) = f.name() { |
168 | if name.text().eq_ignore_ascii_case("new") { | 168 | if name.text().eq_ignore_ascii_case("new") { |
169 | return true; | 169 | return true; |
diff --git a/crates/ra_assists/src/handlers/change_visibility.rs b/crates/ra_assists/src/handlers/change_visibility.rs index 44f6a1dae..1cd532e80 100644 --- a/crates/ra_assists/src/handlers/change_visibility.rs +++ b/crates/ra_assists/src/handlers/change_visibility.rs | |||
@@ -47,8 +47,7 @@ fn add_vis(ctx: AssistCtx) -> Option<Assist> { | |||
47 | return None; | 47 | return None; |
48 | } | 48 | } |
49 | (vis_offset(&parent), keyword.text_range()) | 49 | (vis_offset(&parent), keyword.text_range()) |
50 | } else { | 50 | } else if let Some(field_name) = ctx.find_node_at_offset::<ast::Name>() { |
51 | let field_name: ast::Name = ctx.find_node_at_offset()?; | ||
52 | let field = field_name.syntax().ancestors().find_map(ast::RecordFieldDef::cast)?; | 51 | let field = field_name.syntax().ancestors().find_map(ast::RecordFieldDef::cast)?; |
53 | if field.name()? != field_name { | 52 | if field.name()? != field_name { |
54 | tested_by!(change_visibility_field_false_positive); | 53 | tested_by!(change_visibility_field_false_positive); |
@@ -58,6 +57,13 @@ fn add_vis(ctx: AssistCtx) -> Option<Assist> { | |||
58 | return None; | 57 | return None; |
59 | } | 58 | } |
60 | (vis_offset(field.syntax()), field_name.syntax().text_range()) | 59 | (vis_offset(field.syntax()), field_name.syntax().text_range()) |
60 | } else if let Some(field) = ctx.find_node_at_offset::<ast::TupleFieldDef>() { | ||
61 | if field.visibility().is_some() { | ||
62 | return None; | ||
63 | } | ||
64 | (vis_offset(field.syntax()), field.syntax().text_range()) | ||
65 | } else { | ||
66 | return None; | ||
61 | }; | 67 | }; |
62 | 68 | ||
63 | ctx.add_assist(AssistId("change_visibility"), "Change visibility to pub(crate)", |edit| { | 69 | ctx.add_assist(AssistId("change_visibility"), "Change visibility to pub(crate)", |edit| { |
@@ -129,7 +135,8 @@ mod tests { | |||
129 | change_visibility, | 135 | change_visibility, |
130 | r"struct S { <|>field: u32 }", | 136 | r"struct S { <|>field: u32 }", |
131 | r"struct S { <|>pub(crate) field: u32 }", | 137 | r"struct S { <|>pub(crate) field: u32 }", |
132 | ) | 138 | ); |
139 | check_assist(change_visibility, r"struct S ( <|>u32 )", r"struct S ( <|>pub(crate) u32 )"); | ||
133 | } | 140 | } |
134 | 141 | ||
135 | #[test] | 142 | #[test] |
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs index 6be704ce3..2f15a3f15 100644 --- a/crates/ra_assists/src/utils.rs +++ b/crates/ra_assists/src/utils.rs | |||
@@ -13,7 +13,7 @@ use rustc_hash::FxHashSet; | |||
13 | 13 | ||
14 | pub(crate) use insert_use::insert_use_statement; | 14 | pub(crate) use insert_use::insert_use_statement; |
15 | 15 | ||
16 | pub fn get_missing_impl_items( | 16 | pub fn get_missing_assoc_items( |
17 | sema: &Semantics<RootDatabase>, | 17 | sema: &Semantics<RootDatabase>, |
18 | impl_def: &ast::ImplDef, | 18 | impl_def: &ast::ImplDef, |
19 | ) -> Vec<hir::AssocItem> { | 19 | ) -> Vec<hir::AssocItem> { |
@@ -23,21 +23,21 @@ pub fn get_missing_impl_items( | |||
23 | let mut impl_type = FxHashSet::default(); | 23 | let mut impl_type = FxHashSet::default(); |
24 | 24 | ||
25 | if let Some(item_list) = impl_def.item_list() { | 25 | if let Some(item_list) = impl_def.item_list() { |
26 | for item in item_list.impl_items() { | 26 | for item in item_list.assoc_items() { |
27 | match item { | 27 | match item { |
28 | ast::ImplItem::FnDef(f) => { | 28 | ast::AssocItem::FnDef(f) => { |
29 | if let Some(n) = f.name() { | 29 | if let Some(n) = f.name() { |
30 | impl_fns_consts.insert(n.syntax().to_string()); | 30 | impl_fns_consts.insert(n.syntax().to_string()); |
31 | } | 31 | } |
32 | } | 32 | } |
33 | 33 | ||
34 | ast::ImplItem::TypeAliasDef(t) => { | 34 | ast::AssocItem::TypeAliasDef(t) => { |
35 | if let Some(n) = t.name() { | 35 | if let Some(n) = t.name() { |
36 | impl_type.insert(n.syntax().to_string()); | 36 | impl_type.insert(n.syntax().to_string()); |
37 | } | 37 | } |
38 | } | 38 | } |
39 | 39 | ||
40 | ast::ImplItem::ConstDef(c) => { | 40 | ast::AssocItem::ConstDef(c) => { |
41 | if let Some(n) = c.name() { | 41 | if let Some(n) = c.name() { |
42 | impl_fns_consts.insert(n.syntax().to_string()); | 42 | impl_fns_consts.insert(n.syntax().to_string()); |
43 | } | 43 | } |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index a004363ee..5f480c304 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -1211,7 +1211,7 @@ impl Type { | |||
1211 | 1211 | ||
1212 | // This would be nicer if it just returned an iterator, but that runs into | 1212 | // This would be nicer if it just returned an iterator, but that runs into |
1213 | // lifetime problems, because we need to borrow temp `CrateImplDefs`. | 1213 | // lifetime problems, because we need to borrow temp `CrateImplDefs`. |
1214 | pub fn iterate_impl_items<T>( | 1214 | pub fn iterate_assoc_items<T>( |
1215 | self, | 1215 | self, |
1216 | db: &dyn HirDatabase, | 1216 | db: &dyn HirDatabase, |
1217 | krate: Crate, | 1217 | krate: Crate, |
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index d0912ddaa..2bc34d449 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs | |||
@@ -118,11 +118,12 @@ fn lower_enum( | |||
118 | module_id: ModuleId, | 118 | module_id: ModuleId, |
119 | ) { | 119 | ) { |
120 | let expander = CfgExpander::new(db, ast.file_id, module_id.krate); | 120 | let expander = CfgExpander::new(db, ast.file_id, module_id.krate); |
121 | let variants = | 121 | let variants = ast |
122 | ast.value.variant_list().into_iter().flat_map(|it| it.variants()).filter(|var| { | 122 | .value |
123 | let attrs = expander.parse_attrs(var); | 123 | .variant_list() |
124 | expander.is_cfg_enabled(&attrs) | 124 | .into_iter() |
125 | }); | 125 | .flat_map(|it| it.variants()) |
126 | .filter(|var| expander.is_cfg_enabled(var)); | ||
126 | for var in variants { | 127 | for var in variants { |
127 | trace.alloc( | 128 | trace.alloc( |
128 | || var.clone(), | 129 | || var.clone(), |
@@ -215,8 +216,7 @@ fn lower_struct( | |||
215 | match &ast.value { | 216 | match &ast.value { |
216 | ast::StructKind::Tuple(fl) => { | 217 | ast::StructKind::Tuple(fl) => { |
217 | for (i, fd) in fl.fields().enumerate() { | 218 | for (i, fd) in fl.fields().enumerate() { |
218 | let attrs = expander.parse_attrs(&fd); | 219 | if !expander.is_cfg_enabled(&fd) { |
219 | if !expander.is_cfg_enabled(&attrs) { | ||
220 | continue; | 220 | continue; |
221 | } | 221 | } |
222 | 222 | ||
@@ -233,8 +233,7 @@ fn lower_struct( | |||
233 | } | 233 | } |
234 | ast::StructKind::Record(fl) => { | 234 | ast::StructKind::Record(fl) => { |
235 | for fd in fl.fields() { | 235 | for fd in fl.fields() { |
236 | let attrs = expander.parse_attrs(&fd); | 236 | if !expander.is_cfg_enabled(&fd) { |
237 | if !expander.is_cfg_enabled(&attrs) { | ||
238 | continue; | 237 | continue; |
239 | } | 238 | } |
240 | 239 | ||
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 4edaad960..f5a7305dc 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -60,7 +60,8 @@ impl CfgExpander { | |||
60 | Attrs::new(owner, &self.hygiene) | 60 | Attrs::new(owner, &self.hygiene) |
61 | } | 61 | } |
62 | 62 | ||
63 | pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { | 63 | pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool { |
64 | let attrs = self.parse_attrs(owner); | ||
64 | attrs.is_cfg_enabled(&self.cfg_options) | 65 | attrs.is_cfg_enabled(&self.cfg_options) |
65 | } | 66 | } |
66 | } | 67 | } |
@@ -141,12 +142,8 @@ impl Expander { | |||
141 | InFile { file_id: self.current_file_id, value } | 142 | InFile { file_id: self.current_file_id, value } |
142 | } | 143 | } |
143 | 144 | ||
144 | pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { | 145 | pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool { |
145 | self.cfg_expander.parse_attrs(owner) | 146 | self.cfg_expander.is_cfg_enabled(owner) |
146 | } | ||
147 | |||
148 | pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { | ||
149 | self.cfg_expander.is_cfg_enabled(attrs) | ||
150 | } | 147 | } |
151 | 148 | ||
152 | fn parse_path(&mut self, path: ast::Path) -> Option<Path> { | 149 | fn parse_path(&mut self, path: ast::Path) -> Option<Path> { |
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 687216dc3..443b057ab 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -162,8 +162,7 @@ impl ExprCollector<'_> { | |||
162 | 162 | ||
163 | fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { | 163 | fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { |
164 | let syntax_ptr = AstPtr::new(&expr); | 164 | let syntax_ptr = AstPtr::new(&expr); |
165 | let attrs = self.expander.parse_attrs(&expr); | 165 | if !self.expander.is_cfg_enabled(&expr) { |
166 | if !self.expander.is_cfg_enabled(&attrs) { | ||
167 | return self.missing_expr(); | 166 | return self.missing_expr(); |
168 | } | 167 | } |
169 | match expr { | 168 | match expr { |
@@ -329,8 +328,7 @@ impl ExprCollector<'_> { | |||
329 | .fields() | 328 | .fields() |
330 | .inspect(|field| field_ptrs.push(AstPtr::new(field))) | 329 | .inspect(|field| field_ptrs.push(AstPtr::new(field))) |
331 | .filter_map(|field| { | 330 | .filter_map(|field| { |
332 | let attrs = self.expander.parse_attrs(&field); | 331 | if !self.expander.is_cfg_enabled(&field) { |
333 | if !self.expander.is_cfg_enabled(&attrs) { | ||
334 | return None; | 332 | return None; |
335 | } | 333 | } |
336 | let name = field.field_name()?.as_name(); | 334 | let name = field.field_name()?.as_name(); |
@@ -575,9 +573,16 @@ impl ExprCollector<'_> { | |||
575 | self.body.item_scope.define_def(def); | 573 | self.body.item_scope.define_def(def); |
576 | if let Some(name) = name { | 574 | if let Some(name) = name { |
577 | let vis = crate::visibility::Visibility::Public; // FIXME determine correctly | 575 | let vis = crate::visibility::Visibility::Public; // FIXME determine correctly |
578 | self.body | 576 | let has_constructor = match def { |
579 | .item_scope | 577 | ModuleDefId::AdtId(AdtId::StructId(s)) => { |
580 | .push_res(name.as_name(), crate::per_ns::PerNs::from_def(def, vis)); | 578 | self.db.struct_data(s).variant_data.kind() != StructKind::Record |
579 | } | ||
580 | _ => true, | ||
581 | }; | ||
582 | self.body.item_scope.push_res( | ||
583 | name.as_name(), | ||
584 | crate::per_ns::PerNs::from_def(def, vis, has_constructor), | ||
585 | ); | ||
581 | } | 586 | } |
582 | } | 587 | } |
583 | } | 588 | } |
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index d4cba4d05..e7eb2bb11 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -9,7 +9,7 @@ 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, TypeBoundsOwner, | 12 | self, AssocItem, AstNode, ModuleItemOwner, NameOwner, TypeAscriptionOwner, TypeBoundsOwner, |
13 | VisibilityOwner, | 13 | VisibilityOwner, |
14 | }; | 14 | }; |
15 | 15 | ||
@@ -164,7 +164,7 @@ impl TraitData { | |||
164 | items.extend(collect_items( | 164 | items.extend(collect_items( |
165 | db, | 165 | db, |
166 | &mut expander, | 166 | &mut expander, |
167 | item_list.impl_items(), | 167 | item_list.assoc_items(), |
168 | src.file_id, | 168 | src.file_id, |
169 | container, | 169 | container, |
170 | )); | 170 | )); |
@@ -219,7 +219,7 @@ impl ImplData { | |||
219 | if let Some(item_list) = src.value.item_list() { | 219 | if let Some(item_list) = src.value.item_list() { |
220 | let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); | 220 | let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); |
221 | items.extend( | 221 | items.extend( |
222 | collect_items(db, &mut expander, item_list.impl_items(), src.file_id, container) | 222 | collect_items(db, &mut expander, item_list.assoc_items(), src.file_id, container) |
223 | .into_iter() | 223 | .into_iter() |
224 | .map(|(_, item)| item), | 224 | .map(|(_, item)| item), |
225 | ); | 225 | ); |
@@ -304,7 +304,7 @@ fn collect_items_in_macro( | |||
304 | let mut res = collect_items( | 304 | let mut res = collect_items( |
305 | db, | 305 | db, |
306 | expander, | 306 | expander, |
307 | items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), | 307 | items.value.items().filter_map(|it| AssocItem::cast(it.syntax().clone())), |
308 | items.file_id, | 308 | items.file_id, |
309 | container, | 309 | container, |
310 | ); | 310 | ); |
@@ -325,31 +325,30 @@ fn collect_items_in_macro( | |||
325 | fn collect_items( | 325 | fn collect_items( |
326 | db: &dyn DefDatabase, | 326 | db: &dyn DefDatabase, |
327 | expander: &mut Expander, | 327 | expander: &mut Expander, |
328 | impl_items: impl Iterator<Item = ImplItem>, | 328 | assoc_items: impl Iterator<Item = AssocItem>, |
329 | file_id: crate::HirFileId, | 329 | file_id: crate::HirFileId, |
330 | container: AssocContainerId, | 330 | container: AssocContainerId, |
331 | ) -> Vec<(Name, AssocItemId)> { | 331 | ) -> Vec<(Name, AssocItemId)> { |
332 | let items = db.ast_id_map(file_id); | 332 | let items = db.ast_id_map(file_id); |
333 | 333 | ||
334 | impl_items | 334 | assoc_items |
335 | .filter_map(|item_node| match item_node { | 335 | .filter_map(|item_node| match item_node { |
336 | ast::ImplItem::FnDef(it) => { | 336 | ast::AssocItem::FnDef(it) => { |
337 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); | 337 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); |
338 | let attrs = expander.parse_attrs(&it); | 338 | if !expander.is_cfg_enabled(&it) { |
339 | if !expander.is_cfg_enabled(&attrs) { | ||
340 | return None; | 339 | return None; |
341 | } | 340 | } |
342 | let def = FunctionLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } | 341 | let def = FunctionLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } |
343 | .intern(db); | 342 | .intern(db); |
344 | Some((name, def.into())) | 343 | Some((name, def.into())) |
345 | } | 344 | } |
346 | ast::ImplItem::ConstDef(it) => { | 345 | ast::AssocItem::ConstDef(it) => { |
347 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); | 346 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); |
348 | let def = ConstLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } | 347 | let def = ConstLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } |
349 | .intern(db); | 348 | .intern(db); |
350 | Some((name, def.into())) | 349 | Some((name, def.into())) |
351 | } | 350 | } |
352 | ast::ImplItem::TypeAliasDef(it) => { | 351 | ast::AssocItem::TypeAliasDef(it) => { |
353 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); | 352 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); |
354 | let def = | 353 | let def = |
355 | TypeAliasLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } | 354 | TypeAliasLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } |
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 259b9ff03..fc15948ad 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs | |||
@@ -151,13 +151,20 @@ impl ItemScope { | |||
151 | } | 151 | } |
152 | 152 | ||
153 | impl PerNs { | 153 | impl PerNs { |
154 | pub(crate) fn from_def(def: ModuleDefId, v: Visibility) -> PerNs { | 154 | pub(crate) fn from_def(def: ModuleDefId, v: Visibility, has_constructor: bool) -> PerNs { |
155 | match def { | 155 | match def { |
156 | ModuleDefId::ModuleId(_) => PerNs::types(def, v), | 156 | ModuleDefId::ModuleId(_) => PerNs::types(def, v), |
157 | ModuleDefId::FunctionId(_) => PerNs::values(def, v), | 157 | ModuleDefId::FunctionId(_) => PerNs::values(def, v), |
158 | ModuleDefId::AdtId(adt) => match adt { | 158 | ModuleDefId::AdtId(adt) => match adt { |
159 | AdtId::StructId(_) | AdtId::UnionId(_) => PerNs::both(def, def, v), | 159 | AdtId::UnionId(_) => PerNs::types(def, v), |
160 | AdtId::EnumId(_) => PerNs::types(def, v), | 160 | AdtId::EnumId(_) => PerNs::types(def, v), |
161 | AdtId::StructId(_) => { | ||
162 | if has_constructor { | ||
163 | PerNs::both(def, def, v) | ||
164 | } else { | ||
165 | PerNs::types(def, v) | ||
166 | } | ||
167 | } | ||
161 | }, | 168 | }, |
162 | ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v), | 169 | ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v), |
163 | ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v), | 170 | ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v), |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index bf3968bd6..db994122a 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -830,7 +830,7 @@ impl ModCollector<'_, '_> { | |||
830 | let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; | 830 | let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; |
831 | let def: ModuleDefId = module.into(); | 831 | let def: ModuleDefId = module.into(); |
832 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); | 832 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); |
833 | self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis); | 833 | self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis, false))], vis); |
834 | res | 834 | res |
835 | } | 835 | } |
836 | 836 | ||
@@ -844,6 +844,8 @@ impl ModCollector<'_, '_> { | |||
844 | let name = def.name.clone(); | 844 | let name = def.name.clone(); |
845 | let container = ContainerId::ModuleId(module); | 845 | let container = ContainerId::ModuleId(module); |
846 | let vis = &def.visibility; | 846 | let vis = &def.visibility; |
847 | let mut has_constructor = false; | ||
848 | |||
847 | let def: ModuleDefId = match def.kind { | 849 | let def: ModuleDefId = match def.kind { |
848 | raw::DefKind::Function(ast_id) => FunctionLoc { | 850 | raw::DefKind::Function(ast_id) => FunctionLoc { |
849 | container: container.into(), | 851 | container: container.into(), |
@@ -851,7 +853,8 @@ impl ModCollector<'_, '_> { | |||
851 | } | 853 | } |
852 | .intern(self.def_collector.db) | 854 | .intern(self.def_collector.db) |
853 | .into(), | 855 | .into(), |
854 | raw::DefKind::Struct(ast_id) => { | 856 | raw::DefKind::Struct(ast_id, mode) => { |
857 | has_constructor = mode != raw::StructDefKind::Record; | ||
855 | StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) } | 858 | StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) } |
856 | .intern(self.def_collector.db) | 859 | .intern(self.def_collector.db) |
857 | .into() | 860 | .into() |
@@ -894,7 +897,11 @@ impl ModCollector<'_, '_> { | |||
894 | .def_map | 897 | .def_map |
895 | .resolve_visibility(self.def_collector.db, self.module_id, vis) | 898 | .resolve_visibility(self.def_collector.db, self.module_id, vis) |
896 | .unwrap_or(Visibility::Public); | 899 | .unwrap_or(Visibility::Public); |
897 | self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis) | 900 | self.def_collector.update( |
901 | self.module_id, | ||
902 | &[(name, PerNs::from_def(def, vis, has_constructor))], | ||
903 | vis, | ||
904 | ) | ||
898 | } | 905 | } |
899 | 906 | ||
900 | fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { | 907 | fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { |
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index a71503c76..f2716a295 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs | |||
@@ -156,9 +156,16 @@ pub(super) struct DefData { | |||
156 | } | 156 | } |
157 | 157 | ||
158 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] | 158 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] |
159 | pub(super) enum StructDefKind { | ||
160 | Record, | ||
161 | Tuple, | ||
162 | Unit, | ||
163 | } | ||
164 | |||
165 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] | ||
159 | pub(super) enum DefKind { | 166 | pub(super) enum DefKind { |
160 | Function(FileAstId<ast::FnDef>), | 167 | Function(FileAstId<ast::FnDef>), |
161 | Struct(FileAstId<ast::StructDef>), | 168 | Struct(FileAstId<ast::StructDef>, StructDefKind), |
162 | Union(FileAstId<ast::UnionDef>), | 169 | Union(FileAstId<ast::UnionDef>), |
163 | Enum(FileAstId<ast::EnumDef>), | 170 | Enum(FileAstId<ast::EnumDef>), |
164 | Const(FileAstId<ast::ConstDef>), | 171 | Const(FileAstId<ast::ConstDef>), |
@@ -171,7 +178,7 @@ impl DefKind { | |||
171 | pub fn ast_id(&self) -> FileAstId<ast::ModuleItem> { | 178 | pub fn ast_id(&self) -> FileAstId<ast::ModuleItem> { |
172 | match self { | 179 | match self { |
173 | DefKind::Function(it) => it.upcast(), | 180 | DefKind::Function(it) => it.upcast(), |
174 | DefKind::Struct(it) => it.upcast(), | 181 | DefKind::Struct(it, _) => it.upcast(), |
175 | DefKind::Union(it) => it.upcast(), | 182 | DefKind::Union(it) => it.upcast(), |
176 | DefKind::Enum(it) => it.upcast(), | 183 | DefKind::Enum(it) => it.upcast(), |
177 | DefKind::Const(it) => it.upcast(), | 184 | DefKind::Const(it) => it.upcast(), |
@@ -236,9 +243,14 @@ impl RawItemsCollector { | |||
236 | return; | 243 | return; |
237 | } | 244 | } |
238 | ast::ModuleItem::StructDef(it) => { | 245 | ast::ModuleItem::StructDef(it) => { |
246 | let kind = match it.kind() { | ||
247 | ast::StructKind::Record(_) => StructDefKind::Record, | ||
248 | ast::StructKind::Tuple(_) => StructDefKind::Tuple, | ||
249 | ast::StructKind::Unit => StructDefKind::Unit, | ||
250 | }; | ||
239 | let id = self.source_ast_id_map.ast_id(&it); | 251 | let id = self.source_ast_id_map.ast_id(&it); |
240 | let name = it.name(); | 252 | let name = it.name(); |
241 | (DefKind::Struct(id), name) | 253 | (DefKind::Struct(id, kind), name) |
242 | } | 254 | } |
243 | ast::ModuleItem::UnionDef(it) => { | 255 | ast::ModuleItem::UnionDef(it) => { |
244 | let id = self.source_ast_id_map.ast_id(&it); | 256 | let id = self.source_ast_id_map.ast_id(&it); |
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index 83120fa36..1b66c1aac 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs | |||
@@ -67,7 +67,7 @@ fn crate_def_map_smoke_test() { | |||
67 | ⋮Baz: t v | 67 | ⋮Baz: t v |
68 | ⋮E: t | 68 | ⋮E: t |
69 | ⋮EXT: v | 69 | ⋮EXT: v |
70 | ⋮U: t v | 70 | ⋮U: t |
71 | ⋮ext: v | 71 | ⋮ext: v |
72 | "###) | 72 | "###) |
73 | } | 73 | } |
diff --git a/crates/ra_hir_def/src/nameres/tests/macros.rs b/crates/ra_hir_def/src/nameres/tests/macros.rs index 9bc0e6287..40289e3ca 100644 --- a/crates/ra_hir_def/src/nameres/tests/macros.rs +++ b/crates/ra_hir_def/src/nameres/tests/macros.rs | |||
@@ -19,12 +19,12 @@ fn macro_rules_are_globally_visible() { | |||
19 | ); | 19 | ); |
20 | assert_snapshot!(map, @r###" | 20 | assert_snapshot!(map, @r###" |
21 | ⋮crate | 21 | ⋮crate |
22 | ⋮Foo: t v | 22 | ⋮Foo: t |
23 | ⋮nested: t | 23 | ⋮nested: t |
24 | ⋮ | 24 | ⋮ |
25 | ⋮crate::nested | 25 | ⋮crate::nested |
26 | ⋮Bar: t v | 26 | ⋮Bar: t |
27 | ⋮Baz: t v | 27 | ⋮Baz: t |
28 | "###); | 28 | "###); |
29 | } | 29 | } |
30 | 30 | ||
@@ -91,13 +91,13 @@ fn macro_rules_from_other_crates_are_visible() { | |||
91 | ); | 91 | ); |
92 | assert_snapshot!(map, @r###" | 92 | assert_snapshot!(map, @r###" |
93 | ⋮crate | 93 | ⋮crate |
94 | ⋮Bar: t v | 94 | ⋮Bar: t |
95 | ⋮Foo: t v | 95 | ⋮Foo: t |
96 | ⋮bar: t | 96 | ⋮bar: t |
97 | ⋮ | 97 | ⋮ |
98 | ⋮crate::bar | 98 | ⋮crate::bar |
99 | ⋮Bar: t v | 99 | ⋮Bar: t |
100 | ⋮Foo: t v | 100 | ⋮Foo: t |
101 | ⋮bar: t | 101 | ⋮bar: t |
102 | "###); | 102 | "###); |
103 | } | 103 | } |
@@ -124,13 +124,13 @@ fn macro_rules_export_with_local_inner_macros_are_visible() { | |||
124 | ); | 124 | ); |
125 | assert_snapshot!(map, @r###" | 125 | assert_snapshot!(map, @r###" |
126 | ⋮crate | 126 | ⋮crate |
127 | ⋮Bar: t v | 127 | ⋮Bar: t |
128 | ⋮Foo: t v | 128 | ⋮Foo: t |
129 | ⋮bar: t | 129 | ⋮bar: t |
130 | ⋮ | 130 | ⋮ |
131 | ⋮crate::bar | 131 | ⋮crate::bar |
132 | ⋮Bar: t v | 132 | ⋮Bar: t |
133 | ⋮Foo: t v | 133 | ⋮Foo: t |
134 | ⋮bar: t | 134 | ⋮bar: t |
135 | "###); | 135 | "###); |
136 | } | 136 | } |
@@ -161,13 +161,13 @@ fn local_inner_macros_makes_local_macros_usable() { | |||
161 | ); | 161 | ); |
162 | assert_snapshot!(map, @r###" | 162 | assert_snapshot!(map, @r###" |
163 | ⋮crate | 163 | ⋮crate |
164 | ⋮Bar: t v | 164 | ⋮Bar: t |
165 | ⋮Foo: t v | 165 | ⋮Foo: t |
166 | ⋮bar: t | 166 | ⋮bar: t |
167 | ⋮ | 167 | ⋮ |
168 | ⋮crate::bar | 168 | ⋮crate::bar |
169 | ⋮Bar: t v | 169 | ⋮Bar: t |
170 | ⋮Foo: t v | 170 | ⋮Foo: t |
171 | ⋮bar: t | 171 | ⋮bar: t |
172 | "###); | 172 | "###); |
173 | } | 173 | } |
@@ -204,7 +204,7 @@ fn unexpanded_macro_should_expand_by_fixedpoint_loop() { | |||
204 | ); | 204 | ); |
205 | assert_snapshot!(map, @r###" | 205 | assert_snapshot!(map, @r###" |
206 | ⋮crate | 206 | ⋮crate |
207 | ⋮Foo: t v | 207 | ⋮Foo: t |
208 | ⋮bar: m | 208 | ⋮bar: m |
209 | ⋮foo: m | 209 | ⋮foo: m |
210 | "###); | 210 | "###); |
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index 29e38a06c..07398ddcc 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs | |||
@@ -269,7 +269,7 @@ fn test() { S.foo()<|>; } | |||
269 | } | 269 | } |
270 | 270 | ||
271 | #[test] | 271 | #[test] |
272 | fn infer_impl_items_generated_by_macros() { | 272 | fn infer_assoc_items_generated_by_macros() { |
273 | let t = type_at( | 273 | let t = type_at( |
274 | r#" | 274 | r#" |
275 | //- /main.rs | 275 | //- /main.rs |
@@ -288,7 +288,7 @@ fn test() { S.foo()<|>; } | |||
288 | } | 288 | } |
289 | 289 | ||
290 | #[test] | 290 | #[test] |
291 | fn infer_impl_items_generated_by_macros_chain() { | 291 | fn infer_assoc_items_generated_by_macros_chain() { |
292 | let t = type_at( | 292 | let t = type_at( |
293 | r#" | 293 | r#" |
294 | //- /main.rs | 294 | //- /main.rs |
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs index 8a1292c7a..115ad8328 100644 --- a/crates/ra_hir_ty/src/tests/regression.rs +++ b/crates/ra_hir_ty/src/tests/regression.rs | |||
@@ -535,6 +535,35 @@ fn foo(b: Bar) { | |||
535 | } | 535 | } |
536 | 536 | ||
537 | #[test] | 537 | #[test] |
538 | fn issue_4235_name_conflicts() { | ||
539 | assert_snapshot!( | ||
540 | infer(r#" | ||
541 | struct FOO {} | ||
542 | static FOO:FOO = FOO {}; | ||
543 | |||
544 | impl FOO { | ||
545 | fn foo(&self) {} | ||
546 | } | ||
547 | |||
548 | fn main() { | ||
549 | let a = &FOO; | ||
550 | a.foo(); | ||
551 | } | ||
552 | "#), @r###" | ||
553 | 32..38 'FOO {}': FOO | ||
554 | 64..68 'self': &FOO | ||
555 | 70..72 '{}': () | ||
556 | 86..120 '{ ...o(); }': () | ||
557 | 96..97 'a': &FOO | ||
558 | 100..104 '&FOO': &FOO | ||
559 | 101..104 'FOO': FOO | ||
560 | 110..111 'a': &FOO | ||
561 | 110..117 'a.foo()': () | ||
562 | "### | ||
563 | ); | ||
564 | } | ||
565 | |||
566 | #[test] | ||
538 | fn issue_4053_diesel_where_clauses() { | 567 | fn issue_4053_diesel_where_clauses() { |
539 | assert_snapshot!( | 568 | assert_snapshot!( |
540 | infer(r#" | 569 | infer(r#" |
diff --git a/crates/ra_ide/src/completion/complete_qualified_path.rs b/crates/ra_ide/src/completion/complete_qualified_path.rs index d9ea92ef8..7fcd22525 100644 --- a/crates/ra_ide/src/completion/complete_qualified_path.rs +++ b/crates/ra_ide/src/completion/complete_qualified_path.rs | |||
@@ -84,7 +84,7 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
84 | }); | 84 | }); |
85 | 85 | ||
86 | // Iterate assoc types separately | 86 | // Iterate assoc types separately |
87 | ty.iterate_impl_items(ctx.db, krate, |item| { | 87 | ty.iterate_assoc_items(ctx.db, krate, |item| { |
88 | if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { | 88 | if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { |
89 | return None; | 89 | return None; |
90 | } | 90 | } |
diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs index ee32d1ff6..039df03e0 100644 --- a/crates/ra_ide/src/completion/complete_trait_impl.rs +++ b/crates/ra_ide/src/completion/complete_trait_impl.rs | |||
@@ -32,7 +32,7 @@ | |||
32 | //! ``` | 32 | //! ``` |
33 | 33 | ||
34 | use hir::{self, Docs, HasSource}; | 34 | use hir::{self, Docs, HasSource}; |
35 | use ra_assists::utils::get_missing_impl_items; | 35 | use ra_assists::utils::get_missing_assoc_items; |
36 | use ra_syntax::{ | 36 | use ra_syntax::{ |
37 | ast::{self, edit, ImplDef}, | 37 | ast::{self, edit, ImplDef}, |
38 | AstNode, SyntaxKind, SyntaxNode, TextRange, T, | 38 | AstNode, SyntaxKind, SyntaxNode, TextRange, T, |
@@ -50,7 +50,7 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext | |||
50 | if let Some((trigger, impl_def)) = completion_match(ctx) { | 50 | if let Some((trigger, impl_def)) = completion_match(ctx) { |
51 | match trigger.kind() { | 51 | match trigger.kind() { |
52 | SyntaxKind::NAME_REF => { | 52 | SyntaxKind::NAME_REF => { |
53 | get_missing_impl_items(&ctx.sema, &impl_def).iter().for_each(|item| match item { | 53 | get_missing_assoc_items(&ctx.sema, &impl_def).iter().for_each(|item| match item { |
54 | hir::AssocItem::Function(fn_item) => { | 54 | hir::AssocItem::Function(fn_item) => { |
55 | add_function_impl(&trigger, acc, ctx, &fn_item) | 55 | add_function_impl(&trigger, acc, ctx, &fn_item) |
56 | } | 56 | } |
@@ -64,34 +64,40 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext | |||
64 | } | 64 | } |
65 | 65 | ||
66 | SyntaxKind::FN_DEF => { | 66 | SyntaxKind::FN_DEF => { |
67 | for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map( | 67 | for missing_fn in |
68 | |item| match item { | 68 | get_missing_assoc_items(&ctx.sema, &impl_def).iter().filter_map(|item| { |
69 | hir::AssocItem::Function(fn_item) => Some(fn_item), | 69 | match item { |
70 | _ => None, | 70 | hir::AssocItem::Function(fn_item) => Some(fn_item), |
71 | }, | 71 | _ => None, |
72 | ) { | 72 | } |
73 | }) | ||
74 | { | ||
73 | add_function_impl(&trigger, acc, ctx, &missing_fn); | 75 | add_function_impl(&trigger, acc, ctx, &missing_fn); |
74 | } | 76 | } |
75 | } | 77 | } |
76 | 78 | ||
77 | SyntaxKind::TYPE_ALIAS_DEF => { | 79 | SyntaxKind::TYPE_ALIAS_DEF => { |
78 | for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map( | 80 | for missing_fn in |
79 | |item| match item { | 81 | get_missing_assoc_items(&ctx.sema, &impl_def).iter().filter_map(|item| { |
80 | hir::AssocItem::TypeAlias(type_item) => Some(type_item), | 82 | match item { |
81 | _ => None, | 83 | hir::AssocItem::TypeAlias(type_item) => Some(type_item), |
82 | }, | 84 | _ => None, |
83 | ) { | 85 | } |
86 | }) | ||
87 | { | ||
84 | add_type_alias_impl(&trigger, acc, ctx, &missing_fn); | 88 | add_type_alias_impl(&trigger, acc, ctx, &missing_fn); |
85 | } | 89 | } |
86 | } | 90 | } |
87 | 91 | ||
88 | SyntaxKind::CONST_DEF => { | 92 | SyntaxKind::CONST_DEF => { |
89 | for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map( | 93 | for missing_fn in |
90 | |item| match item { | 94 | get_missing_assoc_items(&ctx.sema, &impl_def).iter().filter_map(|item| { |
91 | hir::AssocItem::Const(const_item) => Some(const_item), | 95 | match item { |
92 | _ => None, | 96 | hir::AssocItem::Const(const_item) => Some(const_item), |
93 | }, | 97 | _ => None, |
94 | ) { | 98 | } |
99 | }) | ||
100 | { | ||
95 | add_const_impl(&trigger, acc, ctx, &missing_fn); | 101 | add_const_impl(&trigger, acc, ctx, &missing_fn); |
96 | } | 102 | } |
97 | } | 103 | } |
diff --git a/crates/ra_ide/src/runnables.rs b/crates/ra_ide/src/runnables.rs index 38637c19c..fa8a9d92c 100644 --- a/crates/ra_ide/src/runnables.rs +++ b/crates/ra_ide/src/runnables.rs | |||
@@ -9,6 +9,7 @@ use ra_syntax::{ | |||
9 | }; | 9 | }; |
10 | 10 | ||
11 | use crate::FileId; | 11 | use crate::FileId; |
12 | use ast::DocCommentsOwner; | ||
12 | use std::fmt::Display; | 13 | use std::fmt::Display; |
13 | 14 | ||
14 | #[derive(Debug)] | 15 | #[derive(Debug)] |
@@ -37,6 +38,7 @@ pub enum RunnableKind { | |||
37 | Test { test_id: TestId, attr: TestAttr }, | 38 | Test { test_id: TestId, attr: TestAttr }, |
38 | TestMod { path: String }, | 39 | TestMod { path: String }, |
39 | Bench { test_id: TestId }, | 40 | Bench { test_id: TestId }, |
41 | DocTest { test_id: TestId }, | ||
40 | Bin, | 42 | Bin, |
41 | } | 43 | } |
42 | 44 | ||
@@ -81,6 +83,8 @@ fn runnable_fn(sema: &Semantics<RootDatabase>, fn_def: ast::FnDef) -> Option<Run | |||
81 | RunnableKind::Test { test_id, attr } | 83 | RunnableKind::Test { test_id, attr } |
82 | } else if fn_def.has_atom_attr("bench") { | 84 | } else if fn_def.has_atom_attr("bench") { |
83 | RunnableKind::Bench { test_id } | 85 | RunnableKind::Bench { test_id } |
86 | } else if has_doc_test(&fn_def) { | ||
87 | RunnableKind::DocTest { test_id } | ||
84 | } else { | 88 | } else { |
85 | return None; | 89 | return None; |
86 | } | 90 | } |
@@ -117,6 +121,10 @@ fn has_test_related_attribute(fn_def: &ast::FnDef) -> bool { | |||
117 | .any(|attribute_text| attribute_text.contains("test")) | 121 | .any(|attribute_text| attribute_text.contains("test")) |
118 | } | 122 | } |
119 | 123 | ||
124 | fn has_doc_test(fn_def: &ast::FnDef) -> bool { | ||
125 | fn_def.doc_comment_text().map_or(false, |comment| comment.contains("```")) | ||
126 | } | ||
127 | |||
120 | fn runnable_mod(sema: &Semantics<RootDatabase>, module: ast::Module) -> Option<Runnable> { | 128 | fn runnable_mod(sema: &Semantics<RootDatabase>, module: ast::Module) -> Option<Runnable> { |
121 | let has_test_function = module | 129 | let has_test_function = module |
122 | .item_list()? | 130 | .item_list()? |
@@ -195,6 +203,41 @@ mod tests { | |||
195 | } | 203 | } |
196 | 204 | ||
197 | #[test] | 205 | #[test] |
206 | fn test_runnables_doc_test() { | ||
207 | let (analysis, pos) = analysis_and_position( | ||
208 | r#" | ||
209 | //- /lib.rs | ||
210 | <|> //empty | ||
211 | fn main() {} | ||
212 | |||
213 | /// ``` | ||
214 | /// let x = 5; | ||
215 | /// ``` | ||
216 | fn foo() {} | ||
217 | "#, | ||
218 | ); | ||
219 | let runnables = analysis.runnables(pos.file_id).unwrap(); | ||
220 | assert_debug_snapshot!(&runnables, | ||
221 | @r###" | ||
222 | [ | ||
223 | Runnable { | ||
224 | range: 1..21, | ||
225 | kind: Bin, | ||
226 | }, | ||
227 | Runnable { | ||
228 | range: 22..64, | ||
229 | kind: DocTest { | ||
230 | test_id: Path( | ||
231 | "foo", | ||
232 | ), | ||
233 | }, | ||
234 | }, | ||
235 | ] | ||
236 | "### | ||
237 | ); | ||
238 | } | ||
239 | |||
240 | #[test] | ||
198 | fn test_runnables_module() { | 241 | fn test_runnables_module() { |
199 | let (analysis, pos) = analysis_and_position( | 242 | let (analysis, pos) = analysis_and_position( |
200 | r#" | 243 | r#" |
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index bb28acfd9..fc4133a67 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -63,7 +63,7 @@ pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, Toke | |||
63 | // * Items(SmallVec<[P<ast::Item>; 1]>) -> token_tree_to_items | 63 | // * Items(SmallVec<[P<ast::Item>; 1]>) -> token_tree_to_items |
64 | // | 64 | // |
65 | // * TraitItems(SmallVec<[ast::TraitItem; 1]>) | 65 | // * TraitItems(SmallVec<[ast::TraitItem; 1]>) |
66 | // * ImplItems(SmallVec<[ast::ImplItem; 1]>) | 66 | // * AssocItems(SmallVec<[ast::AssocItem; 1]>) |
67 | // * ForeignItems(SmallVec<[ast::ForeignItem; 1]> | 67 | // * ForeignItems(SmallVec<[ast::ForeignItem; 1]> |
68 | 68 | ||
69 | pub fn token_tree_to_syntax_node( | 69 | pub fn token_tree_to_syntax_node( |
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs index c507dc683..3e6dd6061 100644 --- a/crates/ra_syntax/src/ast/edit.rs +++ b/crates/ra_syntax/src/ast/edit.rs | |||
@@ -79,7 +79,7 @@ where | |||
79 | 79 | ||
80 | impl ast::ItemList { | 80 | impl ast::ItemList { |
81 | #[must_use] | 81 | #[must_use] |
82 | pub fn append_items(&self, items: impl IntoIterator<Item = ast::ImplItem>) -> ast::ItemList { | 82 | pub fn append_items(&self, items: impl IntoIterator<Item = ast::AssocItem>) -> ast::ItemList { |
83 | let mut res = self.clone(); | 83 | let mut res = self.clone(); |
84 | if !self.syntax().text().contains_char('\n') { | 84 | if !self.syntax().text().contains_char('\n') { |
85 | res = make_multiline(res); | 85 | res = make_multiline(res); |
@@ -89,8 +89,8 @@ impl ast::ItemList { | |||
89 | } | 89 | } |
90 | 90 | ||
91 | #[must_use] | 91 | #[must_use] |
92 | pub fn append_item(&self, item: ast::ImplItem) -> ast::ItemList { | 92 | pub fn append_item(&self, item: ast::AssocItem) -> ast::ItemList { |
93 | let (indent, position) = match self.impl_items().last() { | 93 | let (indent, position) = match self.assoc_items().last() { |
94 | Some(it) => ( | 94 | Some(it) => ( |
95 | leading_indent(it.syntax()).unwrap_or_default().to_string(), | 95 | leading_indent(it.syntax()).unwrap_or_default().to_string(), |
96 | InsertPosition::After(it.syntax().clone().into()), | 96 | InsertPosition::After(it.syntax().clone().into()), |
diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs index c2cc25958..b00c15608 100644 --- a/crates/ra_syntax/src/ast/generated/nodes.rs +++ b/crates/ra_syntax/src/ast/generated/nodes.rs | |||
@@ -196,7 +196,7 @@ pub struct ItemList { | |||
196 | impl ast::ModuleItemOwner for ItemList {} | 196 | impl ast::ModuleItemOwner for ItemList {} |
197 | impl ItemList { | 197 | impl ItemList { |
198 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | 198 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } |
199 | pub fn impl_items(&self) -> AstChildren<ImplItem> { support::children(&self.syntax) } | 199 | pub fn assoc_items(&self) -> AstChildren<AssocItem> { support::children(&self.syntax) } |
200 | pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } | 200 | pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } |
201 | } | 201 | } |
202 | 202 | ||
@@ -1429,13 +1429,13 @@ impl ast::AttrsOwner for ModuleItem {} | |||
1429 | impl ast::VisibilityOwner for ModuleItem {} | 1429 | impl ast::VisibilityOwner for ModuleItem {} |
1430 | 1430 | ||
1431 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1431 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
1432 | pub enum ImplItem { | 1432 | pub enum AssocItem { |
1433 | FnDef(FnDef), | 1433 | FnDef(FnDef), |
1434 | TypeAliasDef(TypeAliasDef), | 1434 | TypeAliasDef(TypeAliasDef), |
1435 | ConstDef(ConstDef), | 1435 | ConstDef(ConstDef), |
1436 | } | 1436 | } |
1437 | impl ast::NameOwner for ImplItem {} | 1437 | impl ast::NameOwner for AssocItem {} |
1438 | impl ast::AttrsOwner for ImplItem {} | 1438 | impl ast::AttrsOwner for AssocItem {} |
1439 | 1439 | ||
1440 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1440 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
1441 | pub enum ExternItem { | 1441 | pub enum ExternItem { |
@@ -3167,16 +3167,16 @@ impl AstNode for ModuleItem { | |||
3167 | } | 3167 | } |
3168 | } | 3168 | } |
3169 | } | 3169 | } |
3170 | impl From<FnDef> for ImplItem { | 3170 | impl From<FnDef> for AssocItem { |
3171 | fn from(node: FnDef) -> ImplItem { ImplItem::FnDef(node) } | 3171 | fn from(node: FnDef) -> AssocItem { AssocItem::FnDef(node) } |
3172 | } | 3172 | } |
3173 | impl From<TypeAliasDef> for ImplItem { | 3173 | impl From<TypeAliasDef> for AssocItem { |
3174 | fn from(node: TypeAliasDef) -> ImplItem { ImplItem::TypeAliasDef(node) } | 3174 | fn from(node: TypeAliasDef) -> AssocItem { AssocItem::TypeAliasDef(node) } |
3175 | } | 3175 | } |
3176 | impl From<ConstDef> for ImplItem { | 3176 | impl From<ConstDef> for AssocItem { |
3177 | fn from(node: ConstDef) -> ImplItem { ImplItem::ConstDef(node) } | 3177 | fn from(node: ConstDef) -> AssocItem { AssocItem::ConstDef(node) } |
3178 | } | 3178 | } |
3179 | impl AstNode for ImplItem { | 3179 | impl AstNode for AssocItem { |
3180 | fn can_cast(kind: SyntaxKind) -> bool { | 3180 | fn can_cast(kind: SyntaxKind) -> bool { |
3181 | match kind { | 3181 | match kind { |
3182 | FN_DEF | TYPE_ALIAS_DEF | CONST_DEF => true, | 3182 | FN_DEF | TYPE_ALIAS_DEF | CONST_DEF => true, |
@@ -3185,18 +3185,18 @@ impl AstNode for ImplItem { | |||
3185 | } | 3185 | } |
3186 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 3186 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
3187 | let res = match syntax.kind() { | 3187 | let res = match syntax.kind() { |
3188 | FN_DEF => ImplItem::FnDef(FnDef { syntax }), | 3188 | FN_DEF => AssocItem::FnDef(FnDef { syntax }), |
3189 | TYPE_ALIAS_DEF => ImplItem::TypeAliasDef(TypeAliasDef { syntax }), | 3189 | TYPE_ALIAS_DEF => AssocItem::TypeAliasDef(TypeAliasDef { syntax }), |
3190 | CONST_DEF => ImplItem::ConstDef(ConstDef { syntax }), | 3190 | CONST_DEF => AssocItem::ConstDef(ConstDef { syntax }), |
3191 | _ => return None, | 3191 | _ => return None, |
3192 | }; | 3192 | }; |
3193 | Some(res) | 3193 | Some(res) |
3194 | } | 3194 | } |
3195 | fn syntax(&self) -> &SyntaxNode { | 3195 | fn syntax(&self) -> &SyntaxNode { |
3196 | match self { | 3196 | match self { |
3197 | ImplItem::FnDef(it) => &it.syntax, | 3197 | AssocItem::FnDef(it) => &it.syntax, |
3198 | ImplItem::TypeAliasDef(it) => &it.syntax, | 3198 | AssocItem::TypeAliasDef(it) => &it.syntax, |
3199 | ImplItem::ConstDef(it) => &it.syntax, | 3199 | AssocItem::ConstDef(it) => &it.syntax, |
3200 | } | 3200 | } |
3201 | } | 3201 | } |
3202 | } | 3202 | } |
@@ -3641,7 +3641,7 @@ impl std::fmt::Display for ModuleItem { | |||
3641 | std::fmt::Display::fmt(self.syntax(), f) | 3641 | std::fmt::Display::fmt(self.syntax(), f) |
3642 | } | 3642 | } |
3643 | } | 3643 | } |
3644 | impl std::fmt::Display for ImplItem { | 3644 | impl std::fmt::Display for AssocItem { |
3645 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | 3645 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
3646 | std::fmt::Display::fmt(self.syntax(), f) | 3646 | std::fmt::Display::fmt(self.syntax(), f) |
3647 | } | 3647 | } |
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs index 10c25666a..5e5a17943 100644 --- a/crates/rust-analyzer/src/cargo_target_spec.rs +++ b/crates/rust-analyzer/src/cargo_target_spec.rs | |||
@@ -27,7 +27,7 @@ impl CargoTargetSpec { | |||
27 | RunnableKind::Test { test_id, attr } => { | 27 | RunnableKind::Test { test_id, attr } => { |
28 | args.push("test".to_string()); | 28 | args.push("test".to_string()); |
29 | if let Some(spec) = spec { | 29 | if let Some(spec) = spec { |
30 | spec.push_to(&mut args); | 30 | spec.push_to(&mut args, kind); |
31 | } | 31 | } |
32 | extra_args.push(test_id.to_string()); | 32 | extra_args.push(test_id.to_string()); |
33 | if let TestId::Path(_) = test_id { | 33 | if let TestId::Path(_) = test_id { |
@@ -35,13 +35,13 @@ impl CargoTargetSpec { | |||
35 | } | 35 | } |
36 | extra_args.push("--nocapture".to_string()); | 36 | extra_args.push("--nocapture".to_string()); |
37 | if attr.ignore { | 37 | if attr.ignore { |
38 | extra_args.push("--ignored".to_string()) | 38 | extra_args.push("--ignored".to_string()); |
39 | } | 39 | } |
40 | } | 40 | } |
41 | RunnableKind::TestMod { path } => { | 41 | RunnableKind::TestMod { path } => { |
42 | args.push("test".to_string()); | 42 | args.push("test".to_string()); |
43 | if let Some(spec) = spec { | 43 | if let Some(spec) = spec { |
44 | spec.push_to(&mut args); | 44 | spec.push_to(&mut args, kind); |
45 | } | 45 | } |
46 | extra_args.push(path.to_string()); | 46 | extra_args.push(path.to_string()); |
47 | extra_args.push("--nocapture".to_string()); | 47 | extra_args.push("--nocapture".to_string()); |
@@ -49,7 +49,7 @@ impl CargoTargetSpec { | |||
49 | RunnableKind::Bench { test_id } => { | 49 | RunnableKind::Bench { test_id } => { |
50 | args.push("bench".to_string()); | 50 | args.push("bench".to_string()); |
51 | if let Some(spec) = spec { | 51 | if let Some(spec) = spec { |
52 | spec.push_to(&mut args); | 52 | spec.push_to(&mut args, kind); |
53 | } | 53 | } |
54 | extra_args.push(test_id.to_string()); | 54 | extra_args.push(test_id.to_string()); |
55 | if let TestId::Path(_) = test_id { | 55 | if let TestId::Path(_) = test_id { |
@@ -57,10 +57,19 @@ impl CargoTargetSpec { | |||
57 | } | 57 | } |
58 | extra_args.push("--nocapture".to_string()); | 58 | extra_args.push("--nocapture".to_string()); |
59 | } | 59 | } |
60 | RunnableKind::DocTest { test_id } => { | ||
61 | args.push("test".to_string()); | ||
62 | args.push("--doc".to_string()); | ||
63 | if let Some(spec) = spec { | ||
64 | spec.push_to(&mut args, kind); | ||
65 | } | ||
66 | extra_args.push(test_id.to_string()); | ||
67 | extra_args.push("--nocapture".to_string()); | ||
68 | } | ||
60 | RunnableKind::Bin => { | 69 | RunnableKind::Bin => { |
61 | args.push("run".to_string()); | 70 | args.push("run".to_string()); |
62 | if let Some(spec) = spec { | 71 | if let Some(spec) = spec { |
63 | spec.push_to(&mut args); | 72 | spec.push_to(&mut args, kind); |
64 | } | 73 | } |
65 | } | 74 | } |
66 | } | 75 | } |
@@ -91,9 +100,14 @@ impl CargoTargetSpec { | |||
91 | Ok(res) | 100 | Ok(res) |
92 | } | 101 | } |
93 | 102 | ||
94 | pub(crate) fn push_to(self, buf: &mut Vec<String>) { | 103 | pub(crate) fn push_to(self, buf: &mut Vec<String>, kind: &RunnableKind) { |
95 | buf.push("--package".to_string()); | 104 | buf.push("--package".to_string()); |
96 | buf.push(self.package); | 105 | buf.push(self.package); |
106 | |||
107 | // Can't mix --doc with other target flags | ||
108 | if let RunnableKind::DocTest { .. } = kind { | ||
109 | return; | ||
110 | } | ||
97 | match self.target_kind { | 111 | match self.target_kind { |
98 | TargetKind::Bin => { | 112 | TargetKind::Bin => { |
99 | buf.push("--bin".to_string()); | 113 | buf.push("--bin".to_string()); |
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index c7a96ba93..15e8305f8 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs | |||
@@ -835,6 +835,7 @@ pub fn handle_code_lens( | |||
835 | for runnable in world.analysis().runnables(file_id)? { | 835 | for runnable in world.analysis().runnables(file_id)? { |
836 | let title = match &runnable.kind { | 836 | let title = match &runnable.kind { |
837 | RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => "▶️\u{fe0e}Run Test", | 837 | RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => "▶️\u{fe0e}Run Test", |
838 | RunnableKind::DocTest { .. } => "▶️\u{fe0e}Run Doctest", | ||
838 | RunnableKind::Bench { .. } => "Run Bench", | 839 | RunnableKind::Bench { .. } => "Run Bench", |
839 | RunnableKind::Bin => "Run", | 840 | RunnableKind::Bin => "Run", |
840 | } | 841 | } |
@@ -1018,6 +1019,7 @@ fn to_lsp_runnable( | |||
1018 | RunnableKind::Test { test_id, .. } => format!("test {}", test_id), | 1019 | RunnableKind::Test { test_id, .. } => format!("test {}", test_id), |
1019 | RunnableKind::TestMod { path } => format!("test-mod {}", path), | 1020 | RunnableKind::TestMod { path } => format!("test-mod {}", path), |
1020 | RunnableKind::Bench { test_id } => format!("bench {}", test_id), | 1021 | RunnableKind::Bench { test_id } => format!("bench {}", test_id), |
1022 | RunnableKind::DocTest { test_id, .. } => format!("doctest {}", test_id), | ||
1021 | RunnableKind::Bin => "run binary".to_string(), | 1023 | RunnableKind::Bin => "run binary".to_string(), |
1022 | }; | 1024 | }; |
1023 | Ok(req::Runnable { | 1025 | Ok(req::Runnable { |
diff --git a/docs/user/readme.adoc b/docs/user/readme.adoc index b1af72ce6..69f5b13d6 100644 --- a/docs/user/readme.adoc +++ b/docs/user/readme.adoc | |||
@@ -57,7 +57,11 @@ To disable this notification put the following to `settings.json` | |||
57 | ---- | 57 | ---- |
58 | ==== | 58 | ==== |
59 | 59 | ||
60 | The server binary is stored in `~/.config/Code/User/globalStorage/matklad.rust-analyzer` (Linux) or in `~/.Library/Application Support/Code/User/globalStorage/matklad.rust-analyzer` (macOS) or in `%APPDATA%\Code\User\globalStorage` (Windows). | 60 | The server binary is stored in: |
61 | |||
62 | * Linux: `~/.config/Code/User/globalStorage/matklad.rust-analyzer` | ||
63 | * macOS: `~/Library/Application Support/Code/User/globalStorage/matklad.rust-analyzer` | ||
64 | * Windows: `%APPDATA%\Code\User\globalStorage` | ||
61 | 65 | ||
62 | Note that we only support the latest version of VS Code. | 66 | Note that we only support the latest version of VS Code. |
63 | 67 | ||
@@ -159,11 +163,11 @@ Emacs support is maintained as part of the https://github.com/emacs-lsp/lsp-mode | |||
159 | 3. Run `lsp` in a Rust buffer. | 163 | 3. Run `lsp` in a Rust buffer. |
160 | 4. (Optionally) bind commands like `lsp-rust-analyzer-join-lines`, `lsp-extend-selection` and `lsp-rust-analyzer-expand-macro` to keys. | 164 | 4. (Optionally) bind commands like `lsp-rust-analyzer-join-lines`, `lsp-extend-selection` and `lsp-rust-analyzer-expand-macro` to keys. |
161 | 165 | ||
162 | === Vim | 166 | === Vim/NeoVim |
163 | 167 | ||
164 | Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>. | 168 | Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>. Not needed if the extension can install/update it on its own, coc-rust-analyzer is one example. |
165 | 169 | ||
166 | The are several LSP client implementations for vim: | 170 | The are several LSP client implementations for vim or neovim: |
167 | 171 | ||
168 | ==== coc-rust-analyzer | 172 | ==== coc-rust-analyzer |
169 | 173 | ||
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index 2f8065b73..fe3eb85de 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs | |||
@@ -373,7 +373,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { | |||
373 | 373 | ||
374 | struct ItemList: ModuleItemOwner { | 374 | struct ItemList: ModuleItemOwner { |
375 | T!['{'], | 375 | T!['{'], |
376 | impl_items: [ImplItem], | 376 | assoc_items: [AssocItem], |
377 | T!['}'] | 377 | T!['}'] |
378 | } | 378 | } |
379 | 379 | ||
@@ -685,7 +685,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { | |||
685 | } | 685 | } |
686 | 686 | ||
687 | /* impl blocks can also contain MacroCall */ | 687 | /* impl blocks can also contain MacroCall */ |
688 | enum ImplItem: NameOwner, AttrsOwner { | 688 | enum AssocItem: NameOwner, AttrsOwner { |
689 | FnDef, TypeAliasDef, ConstDef | 689 | FnDef, TypeAliasDef, ConstDef |
690 | } | 690 | } |
691 | 691 | ||