diff options
Diffstat (limited to 'crates/ra_hir_def/src')
26 files changed, 662 insertions, 369 deletions
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index 753becc3d..2bc34d449 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs | |||
@@ -12,9 +12,15 @@ use ra_prof::profile; | |||
12 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; | 12 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; |
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
15 | body::CfgExpander, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, | 15 | body::{CfgExpander, LowerCtx}, |
16 | type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId, | 16 | db::DefDatabase, |
17 | LocalFieldId, Lookup, ModuleId, StructId, UnionId, VariantId, | 17 | src::HasChildSource, |
18 | src::HasSource, | ||
19 | trace::Trace, | ||
20 | type_ref::TypeRef, | ||
21 | visibility::RawVisibility, | ||
22 | EnumId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StructId, UnionId, | ||
23 | VariantId, | ||
18 | }; | 24 | }; |
19 | 25 | ||
20 | /// Note that we use `StructData` for unions as well! | 26 | /// Note that we use `StructData` for unions as well! |
@@ -111,7 +117,14 @@ fn lower_enum( | |||
111 | ast: &InFile<ast::EnumDef>, | 117 | ast: &InFile<ast::EnumDef>, |
112 | module_id: ModuleId, | 118 | module_id: ModuleId, |
113 | ) { | 119 | ) { |
114 | for var in ast.value.variant_list().into_iter().flat_map(|it| it.variants()) { | 120 | let expander = CfgExpander::new(db, ast.file_id, module_id.krate); |
121 | let variants = ast | ||
122 | .value | ||
123 | .variant_list() | ||
124 | .into_iter() | ||
125 | .flat_map(|it| it.variants()) | ||
126 | .filter(|var| expander.is_cfg_enabled(var)); | ||
127 | for var in variants { | ||
115 | trace.alloc( | 128 | trace.alloc( |
116 | || var.clone(), | 129 | || var.clone(), |
117 | || EnumVariantData { | 130 | || EnumVariantData { |
@@ -198,11 +211,12 @@ fn lower_struct( | |||
198 | trace: &mut Trace<FieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>, | 211 | trace: &mut Trace<FieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>, |
199 | ast: &InFile<ast::StructKind>, | 212 | ast: &InFile<ast::StructKind>, |
200 | ) -> StructKind { | 213 | ) -> StructKind { |
214 | let ctx = LowerCtx::new(db, ast.file_id); | ||
215 | |||
201 | match &ast.value { | 216 | match &ast.value { |
202 | ast::StructKind::Tuple(fl) => { | 217 | ast::StructKind::Tuple(fl) => { |
203 | for (i, fd) in fl.fields().enumerate() { | 218 | for (i, fd) in fl.fields().enumerate() { |
204 | let attrs = expander.parse_attrs(&fd); | 219 | if !expander.is_cfg_enabled(&fd) { |
205 | if !expander.is_cfg_enabled(&attrs) { | ||
206 | continue; | 220 | continue; |
207 | } | 221 | } |
208 | 222 | ||
@@ -210,7 +224,7 @@ fn lower_struct( | |||
210 | || Either::Left(fd.clone()), | 224 | || Either::Left(fd.clone()), |
211 | || FieldData { | 225 | || FieldData { |
212 | name: Name::new_tuple_field(i), | 226 | name: Name::new_tuple_field(i), |
213 | type_ref: TypeRef::from_ast_opt(fd.type_ref()), | 227 | type_ref: TypeRef::from_ast_opt(&ctx, fd.type_ref()), |
214 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), | 228 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), |
215 | }, | 229 | }, |
216 | ); | 230 | ); |
@@ -219,8 +233,7 @@ fn lower_struct( | |||
219 | } | 233 | } |
220 | ast::StructKind::Record(fl) => { | 234 | ast::StructKind::Record(fl) => { |
221 | for fd in fl.fields() { | 235 | for fd in fl.fields() { |
222 | let attrs = expander.parse_attrs(&fd); | 236 | if !expander.is_cfg_enabled(&fd) { |
223 | if !expander.is_cfg_enabled(&attrs) { | ||
224 | continue; | 237 | continue; |
225 | } | 238 | } |
226 | 239 | ||
@@ -228,7 +241,7 @@ fn lower_struct( | |||
228 | || Either::Right(fd.clone()), | 241 | || Either::Right(fd.clone()), |
229 | || FieldData { | 242 | || FieldData { |
230 | name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), | 243 | name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), |
231 | type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), | 244 | type_ref: TypeRef::from_ast_opt(&ctx, fd.ascribed_type()), |
232 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), | 245 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), |
233 | }, | 246 | }, |
234 | ); | 247 | ); |
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index 5a86af8ba..8b6c0bede 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs | |||
@@ -81,7 +81,7 @@ impl Attrs { | |||
81 | } | 81 | } |
82 | } | 82 | } |
83 | 83 | ||
84 | fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs { | 84 | pub fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs { |
85 | let hygiene = Hygiene::new(db.upcast(), owner.file_id); | 85 | let hygiene = Hygiene::new(db.upcast(), owner.file_id); |
86 | Attrs::new(owner.value, &hygiene) | 86 | Attrs::new(owner.value, &hygiene) |
87 | } | 87 | } |
@@ -140,6 +140,7 @@ impl Attr { | |||
140 | } | 140 | } |
141 | } | 141 | } |
142 | 142 | ||
143 | #[derive(Debug, Clone, Copy)] | ||
143 | pub struct AttrQuery<'a> { | 144 | pub struct AttrQuery<'a> { |
144 | attrs: &'a Attrs, | 145 | attrs: &'a Attrs, |
145 | key: &'static str, | 146 | key: &'static str, |
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 890cefcaf..273036cee 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -15,6 +15,8 @@ use ra_prof::profile; | |||
15 | use ra_syntax::{ast, AstNode, AstPtr}; | 15 | use ra_syntax::{ast, AstNode, AstPtr}; |
16 | use rustc_hash::FxHashMap; | 16 | use rustc_hash::FxHashMap; |
17 | 17 | ||
18 | pub(crate) use lower::LowerCtx; | ||
19 | |||
18 | use crate::{ | 20 | use crate::{ |
19 | attr::Attrs, | 21 | attr::Attrs, |
20 | db::DefDatabase, | 22 | db::DefDatabase, |
@@ -27,7 +29,7 @@ use crate::{ | |||
27 | AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, | 29 | AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, |
28 | }; | 30 | }; |
29 | 31 | ||
30 | /// A subset of Exander that only deals with cfg attributes. We only need it to | 32 | /// A subset of Expander that only deals with cfg attributes. We only need it to |
31 | /// avoid cyclic queries in crate def map during enum processing. | 33 | /// avoid cyclic queries in crate def map during enum processing. |
32 | pub(crate) struct CfgExpander { | 34 | pub(crate) struct CfgExpander { |
33 | cfg_options: CfgOptions, | 35 | cfg_options: CfgOptions, |
@@ -58,7 +60,8 @@ impl CfgExpander { | |||
58 | Attrs::new(owner, &self.hygiene) | 60 | Attrs::new(owner, &self.hygiene) |
59 | } | 61 | } |
60 | 62 | ||
61 | 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); | ||
62 | attrs.is_cfg_enabled(&self.cfg_options) | 65 | attrs.is_cfg_enabled(&self.cfg_options) |
63 | } | 66 | } |
64 | } | 67 | } |
@@ -139,12 +142,8 @@ impl Expander { | |||
139 | InFile { file_id: self.current_file_id, value } | 142 | InFile { file_id: self.current_file_id, value } |
140 | } | 143 | } |
141 | 144 | ||
142 | pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { | 145 | pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool { |
143 | self.cfg_expander.parse_attrs(owner) | 146 | self.cfg_expander.is_cfg_enabled(owner) |
144 | } | ||
145 | |||
146 | pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { | ||
147 | self.cfg_expander.is_cfg_enabled(attrs) | ||
148 | } | 147 | } |
149 | 148 | ||
150 | 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 f467ed3fe..f159f80af 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -3,8 +3,9 @@ | |||
3 | 3 | ||
4 | use either::Either; | 4 | use either::Either; |
5 | use hir_expand::{ | 5 | use hir_expand::{ |
6 | hygiene::Hygiene, | ||
6 | name::{name, AsName, Name}, | 7 | name::{name, AsName, Name}, |
7 | MacroDefId, MacroDefKind, | 8 | HirFileId, MacroDefId, MacroDefKind, |
8 | }; | 9 | }; |
9 | use ra_arena::Arena; | 10 | use ra_arena::Arena; |
10 | use ra_syntax::{ | 11 | use ra_syntax::{ |
@@ -14,7 +15,7 @@ use ra_syntax::{ | |||
14 | }, | 15 | }, |
15 | AstNode, AstPtr, | 16 | AstNode, AstPtr, |
16 | }; | 17 | }; |
17 | use test_utils::tested_by; | 18 | use test_utils::mark; |
18 | 19 | ||
19 | use crate::{ | 20 | use crate::{ |
20 | adt::StructKind, | 21 | adt::StructKind, |
@@ -26,8 +27,8 @@ use crate::{ | |||
26 | LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, | 27 | LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, |
27 | }, | 28 | }, |
28 | item_scope::BuiltinShadowMode, | 29 | item_scope::BuiltinShadowMode, |
29 | path::GenericArgs, | 30 | path::{GenericArgs, Path}, |
30 | type_ref::{Mutability, TypeRef}, | 31 | type_ref::{Mutability, Rawness, TypeRef}, |
31 | AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, | 32 | AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, |
32 | StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, | 33 | StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, |
33 | }; | 34 | }; |
@@ -35,6 +36,23 @@ use crate::{ | |||
35 | use super::{ExprSource, PatSource}; | 36 | use super::{ExprSource, PatSource}; |
36 | use ast::AstChildren; | 37 | use ast::AstChildren; |
37 | 38 | ||
39 | pub(crate) struct LowerCtx { | ||
40 | hygiene: Hygiene, | ||
41 | } | ||
42 | |||
43 | impl LowerCtx { | ||
44 | pub fn new(db: &dyn DefDatabase, file_id: HirFileId) -> Self { | ||
45 | LowerCtx { hygiene: Hygiene::new(db.upcast(), file_id) } | ||
46 | } | ||
47 | pub fn with_hygiene(hygiene: &Hygiene) -> Self { | ||
48 | LowerCtx { hygiene: hygiene.clone() } | ||
49 | } | ||
50 | |||
51 | pub fn lower_path(&self, ast: ast::Path) -> Option<Path> { | ||
52 | Path::from_src(ast, &self.hygiene) | ||
53 | } | ||
54 | } | ||
55 | |||
38 | pub(super) fn lower( | 56 | pub(super) fn lower( |
39 | db: &dyn DefDatabase, | 57 | db: &dyn DefDatabase, |
40 | def: DefWithBodyId, | 58 | def: DefWithBodyId, |
@@ -62,7 +80,6 @@ struct ExprCollector<'a> { | |||
62 | db: &'a dyn DefDatabase, | 80 | db: &'a dyn DefDatabase, |
63 | def: DefWithBodyId, | 81 | def: DefWithBodyId, |
64 | expander: Expander, | 82 | expander: Expander, |
65 | |||
66 | body: Body, | 83 | body: Body, |
67 | source_map: BodySourceMap, | 84 | source_map: BodySourceMap, |
68 | } | 85 | } |
@@ -101,6 +118,10 @@ impl ExprCollector<'_> { | |||
101 | (self.body, self.source_map) | 118 | (self.body, self.source_map) |
102 | } | 119 | } |
103 | 120 | ||
121 | fn ctx(&self) -> LowerCtx { | ||
122 | LowerCtx::new(self.db, self.expander.current_file_id) | ||
123 | } | ||
124 | |||
104 | fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { | 125 | fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { |
105 | let src = self.expander.to_source(ptr); | 126 | let src = self.expander.to_source(ptr); |
106 | let id = self.make_expr(expr, Ok(src.clone())); | 127 | let id = self.make_expr(expr, Ok(src.clone())); |
@@ -113,7 +134,7 @@ impl ExprCollector<'_> { | |||
113 | self.make_expr(expr, Err(SyntheticSyntax)) | 134 | self.make_expr(expr, Err(SyntheticSyntax)) |
114 | } | 135 | } |
115 | fn empty_block(&mut self) -> ExprId { | 136 | fn empty_block(&mut self) -> ExprId { |
116 | self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None }) | 137 | self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None, label: None }) |
117 | } | 138 | } |
118 | fn missing_expr(&mut self) -> ExprId { | 139 | fn missing_expr(&mut self) -> ExprId { |
119 | self.alloc_expr_desugared(Expr::Missing) | 140 | self.alloc_expr_desugared(Expr::Missing) |
@@ -141,8 +162,7 @@ impl ExprCollector<'_> { | |||
141 | 162 | ||
142 | fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { | 163 | fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { |
143 | let syntax_ptr = AstPtr::new(&expr); | 164 | let syntax_ptr = AstPtr::new(&expr); |
144 | let attrs = self.expander.parse_attrs(&expr); | 165 | if !self.expander.is_cfg_enabled(&expr) { |
145 | if !self.expander.is_cfg_enabled(&attrs) { | ||
146 | return self.missing_expr(); | 166 | return self.missing_expr(); |
147 | } | 167 | } |
148 | match expr { | 168 | match expr { |
@@ -182,10 +202,29 @@ impl ExprCollector<'_> { | |||
182 | 202 | ||
183 | self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) | 203 | self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) |
184 | } | 204 | } |
205 | ast::Expr::EffectExpr(e) => match e.effect() { | ||
206 | ast::Effect::Try(_) => { | ||
207 | let body = self.collect_block_opt(e.block_expr()); | ||
208 | self.alloc_expr(Expr::TryBlock { body }, syntax_ptr) | ||
209 | } | ||
210 | // FIXME: we need to record these effects somewhere... | ||
211 | ast::Effect::Async(_) | ast::Effect::Label(_) | ast::Effect::Unsafe(_) => { | ||
212 | self.collect_block_opt(e.block_expr()) | ||
213 | } | ||
214 | }, | ||
185 | ast::Expr::BlockExpr(e) => self.collect_block(e), | 215 | ast::Expr::BlockExpr(e) => self.collect_block(e), |
186 | ast::Expr::LoopExpr(e) => { | 216 | ast::Expr::LoopExpr(e) => { |
187 | let body = self.collect_block_opt(e.loop_body()); | 217 | let body = self.collect_block_opt(e.loop_body()); |
188 | self.alloc_expr(Expr::Loop { body }, syntax_ptr) | 218 | self.alloc_expr( |
219 | Expr::Loop { | ||
220 | body, | ||
221 | label: e | ||
222 | .label() | ||
223 | .and_then(|l| l.lifetime_token()) | ||
224 | .map(|l| Name::new_lifetime(&l)), | ||
225 | }, | ||
226 | syntax_ptr, | ||
227 | ) | ||
189 | } | 228 | } |
190 | ast::Expr::WhileExpr(e) => { | 229 | ast::Expr::WhileExpr(e) => { |
191 | let body = self.collect_block_opt(e.loop_body()); | 230 | let body = self.collect_block_opt(e.loop_body()); |
@@ -196,29 +235,60 @@ impl ExprCollector<'_> { | |||
196 | None => self.collect_expr_opt(condition.expr()), | 235 | None => self.collect_expr_opt(condition.expr()), |
197 | // if let -- desugar to match | 236 | // if let -- desugar to match |
198 | Some(pat) => { | 237 | Some(pat) => { |
199 | tested_by!(infer_resolve_while_let); | 238 | mark::hit!(infer_resolve_while_let); |
200 | let pat = self.collect_pat(pat); | 239 | let pat = self.collect_pat(pat); |
201 | let match_expr = self.collect_expr_opt(condition.expr()); | 240 | let match_expr = self.collect_expr_opt(condition.expr()); |
202 | let placeholder_pat = self.missing_pat(); | 241 | let placeholder_pat = self.missing_pat(); |
203 | let break_ = self.alloc_expr_desugared(Expr::Break { expr: None }); | 242 | let break_ = |
243 | self.alloc_expr_desugared(Expr::Break { expr: None, label: None }); | ||
204 | let arms = vec![ | 244 | let arms = vec![ |
205 | MatchArm { pat, expr: body, guard: None }, | 245 | MatchArm { pat, expr: body, guard: None }, |
206 | MatchArm { pat: placeholder_pat, expr: break_, guard: None }, | 246 | MatchArm { pat: placeholder_pat, expr: break_, guard: None }, |
207 | ]; | 247 | ]; |
208 | let match_expr = | 248 | let match_expr = |
209 | self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); | 249 | self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); |
210 | return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr); | 250 | return self.alloc_expr( |
251 | Expr::Loop { | ||
252 | body: match_expr, | ||
253 | label: e | ||
254 | .label() | ||
255 | .and_then(|l| l.lifetime_token()) | ||
256 | .map(|l| Name::new_lifetime(&l)), | ||
257 | }, | ||
258 | syntax_ptr, | ||
259 | ); | ||
211 | } | 260 | } |
212 | }, | 261 | }, |
213 | }; | 262 | }; |
214 | 263 | ||
215 | self.alloc_expr(Expr::While { condition, body }, syntax_ptr) | 264 | self.alloc_expr( |
265 | Expr::While { | ||
266 | condition, | ||
267 | body, | ||
268 | label: e | ||
269 | .label() | ||
270 | .and_then(|l| l.lifetime_token()) | ||
271 | .map(|l| Name::new_lifetime(&l)), | ||
272 | }, | ||
273 | syntax_ptr, | ||
274 | ) | ||
216 | } | 275 | } |
217 | ast::Expr::ForExpr(e) => { | 276 | ast::Expr::ForExpr(e) => { |
218 | let iterable = self.collect_expr_opt(e.iterable()); | 277 | let iterable = self.collect_expr_opt(e.iterable()); |
219 | let pat = self.collect_pat_opt(e.pat()); | 278 | let pat = self.collect_pat_opt(e.pat()); |
220 | let body = self.collect_block_opt(e.loop_body()); | 279 | let body = self.collect_block_opt(e.loop_body()); |
221 | self.alloc_expr(Expr::For { iterable, pat, body }, syntax_ptr) | 280 | self.alloc_expr( |
281 | Expr::For { | ||
282 | iterable, | ||
283 | pat, | ||
284 | body, | ||
285 | label: e | ||
286 | .label() | ||
287 | .and_then(|l| l.lifetime_token()) | ||
288 | .map(|l| Name::new_lifetime(&l)), | ||
289 | }, | ||
290 | syntax_ptr, | ||
291 | ) | ||
222 | } | 292 | } |
223 | ast::Expr::CallExpr(e) => { | 293 | ast::Expr::CallExpr(e) => { |
224 | let callee = self.collect_expr_opt(e.expr()); | 294 | let callee = self.collect_expr_opt(e.expr()); |
@@ -237,7 +307,8 @@ impl ExprCollector<'_> { | |||
237 | Vec::new() | 307 | Vec::new() |
238 | }; | 308 | }; |
239 | let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); | 309 | let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); |
240 | let generic_args = e.type_arg_list().and_then(GenericArgs::from_ast); | 310 | let generic_args = |
311 | e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it)); | ||
241 | self.alloc_expr( | 312 | self.alloc_expr( |
242 | Expr::MethodCall { receiver, method_name, args, generic_args }, | 313 | Expr::MethodCall { receiver, method_name, args, generic_args }, |
243 | syntax_ptr, | 314 | syntax_ptr, |
@@ -270,13 +341,16 @@ impl ExprCollector<'_> { | |||
270 | .unwrap_or(Expr::Missing); | 341 | .unwrap_or(Expr::Missing); |
271 | self.alloc_expr(path, syntax_ptr) | 342 | self.alloc_expr(path, syntax_ptr) |
272 | } | 343 | } |
273 | ast::Expr::ContinueExpr(_e) => { | 344 | ast::Expr::ContinueExpr(e) => self.alloc_expr( |
274 | // FIXME: labels | 345 | Expr::Continue { label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) }, |
275 | self.alloc_expr(Expr::Continue, syntax_ptr) | 346 | syntax_ptr, |
276 | } | 347 | ), |
277 | ast::Expr::BreakExpr(e) => { | 348 | ast::Expr::BreakExpr(e) => { |
278 | let expr = e.expr().map(|e| self.collect_expr(e)); | 349 | let expr = e.expr().map(|e| self.collect_expr(e)); |
279 | self.alloc_expr(Expr::Break { expr }, syntax_ptr) | 350 | self.alloc_expr( |
351 | Expr::Break { expr, label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) }, | ||
352 | syntax_ptr, | ||
353 | ) | ||
280 | } | 354 | } |
281 | ast::Expr::ParenExpr(e) => { | 355 | ast::Expr::ParenExpr(e) => { |
282 | let inner = self.collect_expr_opt(e.expr()); | 356 | let inner = self.collect_expr_opt(e.expr()); |
@@ -297,8 +371,7 @@ impl ExprCollector<'_> { | |||
297 | .fields() | 371 | .fields() |
298 | .inspect(|field| field_ptrs.push(AstPtr::new(field))) | 372 | .inspect(|field| field_ptrs.push(AstPtr::new(field))) |
299 | .filter_map(|field| { | 373 | .filter_map(|field| { |
300 | let attrs = self.expander.parse_attrs(&field); | 374 | if !self.expander.is_cfg_enabled(&field) { |
301 | if !self.expander.is_cfg_enabled(&attrs) { | ||
302 | return None; | 375 | return None; |
303 | } | 376 | } |
304 | let name = field.field_name()?.as_name(); | 377 | let name = field.field_name()?.as_name(); |
@@ -343,13 +416,26 @@ impl ExprCollector<'_> { | |||
343 | } | 416 | } |
344 | ast::Expr::CastExpr(e) => { | 417 | ast::Expr::CastExpr(e) => { |
345 | let expr = self.collect_expr_opt(e.expr()); | 418 | let expr = self.collect_expr_opt(e.expr()); |
346 | let type_ref = TypeRef::from_ast_opt(e.type_ref()); | 419 | let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.type_ref()); |
347 | self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) | 420 | self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) |
348 | } | 421 | } |
349 | ast::Expr::RefExpr(e) => { | 422 | ast::Expr::RefExpr(e) => { |
350 | let expr = self.collect_expr_opt(e.expr()); | 423 | let expr = self.collect_expr_opt(e.expr()); |
351 | let mutability = Mutability::from_mutable(e.mut_token().is_some()); | 424 | let raw_tok = e.raw_token().is_some(); |
352 | self.alloc_expr(Expr::Ref { expr, mutability }, syntax_ptr) | 425 | let mutability = if raw_tok { |
426 | if e.mut_token().is_some() { | ||
427 | Mutability::Mut | ||
428 | } else if e.const_token().is_some() { | ||
429 | Mutability::Shared | ||
430 | } else { | ||
431 | unreachable!("parser only remaps to raw_token() if matching mutability token follows") | ||
432 | } | ||
433 | } else { | ||
434 | Mutability::from_mutable(e.mut_token().is_some()) | ||
435 | }; | ||
436 | let rawness = Rawness::from_raw(raw_tok); | ||
437 | |||
438 | self.alloc_expr(Expr::Ref { expr, rawness, mutability }, syntax_ptr) | ||
353 | } | 439 | } |
354 | ast::Expr::PrefixExpr(e) => { | 440 | ast::Expr::PrefixExpr(e) => { |
355 | let expr = self.collect_expr_opt(e.expr()); | 441 | let expr = self.collect_expr_opt(e.expr()); |
@@ -365,12 +451,16 @@ impl ExprCollector<'_> { | |||
365 | if let Some(pl) = e.param_list() { | 451 | if let Some(pl) = e.param_list() { |
366 | for param in pl.params() { | 452 | for param in pl.params() { |
367 | let pat = self.collect_pat_opt(param.pat()); | 453 | let pat = self.collect_pat_opt(param.pat()); |
368 | let type_ref = param.ascribed_type().map(TypeRef::from_ast); | 454 | let type_ref = |
455 | param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it)); | ||
369 | args.push(pat); | 456 | args.push(pat); |
370 | arg_types.push(type_ref); | 457 | arg_types.push(type_ref); |
371 | } | 458 | } |
372 | } | 459 | } |
373 | let ret_type = e.ret_type().and_then(|r| r.type_ref()).map(TypeRef::from_ast); | 460 | let ret_type = e |
461 | .ret_type() | ||
462 | .and_then(|r| r.type_ref()) | ||
463 | .map(|it| TypeRef::from_ast(&self.ctx(), it)); | ||
374 | let body = self.collect_expr_opt(e.body()); | 464 | let body = self.collect_expr_opt(e.body()); |
375 | self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) | 465 | self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) |
376 | } | 466 | } |
@@ -430,6 +520,7 @@ impl ExprCollector<'_> { | |||
430 | krate: Some(self.expander.module.krate), | 520 | krate: Some(self.expander.module.krate), |
431 | ast_id: Some(self.expander.ast_id(&e)), | 521 | ast_id: Some(self.expander.ast_id(&e)), |
432 | kind: MacroDefKind::Declarative, | 522 | kind: MacroDefKind::Declarative, |
523 | local_inner: false, | ||
433 | }; | 524 | }; |
434 | self.body.item_scope.define_legacy_macro(name, mac); | 525 | self.body.item_scope.define_legacy_macro(name, mac); |
435 | 526 | ||
@@ -464,19 +555,16 @@ impl ExprCollector<'_> { | |||
464 | } | 555 | } |
465 | } | 556 | } |
466 | 557 | ||
467 | fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId { | 558 | fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId { |
468 | let syntax_node_ptr = AstPtr::new(&expr.clone().into()); | 559 | let syntax_node_ptr = AstPtr::new(&block.clone().into()); |
469 | let block = match expr.block() { | ||
470 | Some(block) => block, | ||
471 | None => return self.alloc_expr(Expr::Missing, syntax_node_ptr), | ||
472 | }; | ||
473 | self.collect_block_items(&block); | 560 | self.collect_block_items(&block); |
474 | let statements = block | 561 | let statements = block |
475 | .statements() | 562 | .statements() |
476 | .map(|s| match s { | 563 | .map(|s| match s { |
477 | ast::Stmt::LetStmt(stmt) => { | 564 | ast::Stmt::LetStmt(stmt) => { |
478 | let pat = self.collect_pat_opt(stmt.pat()); | 565 | let pat = self.collect_pat_opt(stmt.pat()); |
479 | let type_ref = stmt.ascribed_type().map(TypeRef::from_ast); | 566 | let type_ref = |
567 | stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it)); | ||
480 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); | 568 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); |
481 | Statement::Let { pat, type_ref, initializer } | 569 | Statement::Let { pat, type_ref, initializer } |
482 | } | 570 | } |
@@ -484,10 +572,11 @@ impl ExprCollector<'_> { | |||
484 | }) | 572 | }) |
485 | .collect(); | 573 | .collect(); |
486 | let tail = block.expr().map(|e| self.collect_expr(e)); | 574 | let tail = block.expr().map(|e| self.collect_expr(e)); |
487 | self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) | 575 | let label = block.label().and_then(|l| l.lifetime_token()).map(|t| Name::new_lifetime(&t)); |
576 | self.alloc_expr(Expr::Block { statements, tail, label }, syntax_node_ptr) | ||
488 | } | 577 | } |
489 | 578 | ||
490 | fn collect_block_items(&mut self, block: &ast::Block) { | 579 | fn collect_block_items(&mut self, block: &ast::BlockExpr) { |
491 | let container = ContainerId::DefWithBodyId(self.def); | 580 | let container = ContainerId::DefWithBodyId(self.def); |
492 | for item in block.items() { | 581 | for item in block.items() { |
493 | let (def, name): (ModuleDefId, Option<ast::Name>) = match item { | 582 | let (def, name): (ModuleDefId, Option<ast::Name>) = match item { |
@@ -542,9 +631,16 @@ impl ExprCollector<'_> { | |||
542 | self.body.item_scope.define_def(def); | 631 | self.body.item_scope.define_def(def); |
543 | if let Some(name) = name { | 632 | if let Some(name) = name { |
544 | let vis = crate::visibility::Visibility::Public; // FIXME determine correctly | 633 | let vis = crate::visibility::Visibility::Public; // FIXME determine correctly |
545 | self.body | 634 | let has_constructor = match def { |
546 | .item_scope | 635 | ModuleDefId::AdtId(AdtId::StructId(s)) => { |
547 | .push_res(name.as_name(), crate::per_ns::PerNs::from_def(def, vis)); | 636 | self.db.struct_data(s).variant_data.kind() != StructKind::Record |
637 | } | ||
638 | _ => true, | ||
639 | }; | ||
640 | self.body.item_scope.push_res( | ||
641 | name.as_name(), | ||
642 | crate::per_ns::PerNs::from_def(def, vis, has_constructor), | ||
643 | ); | ||
548 | } | 644 | } |
549 | } | 645 | } |
550 | } | 646 | } |
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs index 86f953c80..e48ff38f9 100644 --- a/crates/ra_hir_def/src/body/scope.rs +++ b/crates/ra_hir_def/src/body/scope.rs | |||
@@ -138,10 +138,10 @@ fn compute_block_scopes( | |||
138 | fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { | 138 | fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { |
139 | scopes.set_scope(expr, scope); | 139 | scopes.set_scope(expr, scope); |
140 | match &body[expr] { | 140 | match &body[expr] { |
141 | Expr::Block { statements, tail } => { | 141 | Expr::Block { statements, tail, .. } => { |
142 | compute_block_scopes(&statements, *tail, body, scopes, scope); | 142 | compute_block_scopes(&statements, *tail, body, scopes, scope); |
143 | } | 143 | } |
144 | Expr::For { iterable, pat, body: body_expr } => { | 144 | Expr::For { iterable, pat, body: body_expr, .. } => { |
145 | compute_expr_scopes(*iterable, body, scopes, scope); | 145 | compute_expr_scopes(*iterable, body, scopes, scope); |
146 | let scope = scopes.new_scope(scope); | 146 | let scope = scopes.new_scope(scope); |
147 | scopes.add_bindings(body, scope, *pat); | 147 | scopes.add_bindings(body, scope, *pat); |
@@ -174,7 +174,7 @@ mod tests { | |||
174 | use hir_expand::{name::AsName, InFile}; | 174 | use hir_expand::{name::AsName, InFile}; |
175 | use ra_db::{fixture::WithFixture, FileId, SourceDatabase}; | 175 | use ra_db::{fixture::WithFixture, FileId, SourceDatabase}; |
176 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; | 176 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; |
177 | use test_utils::{assert_eq_text, covers, extract_offset}; | 177 | use test_utils::{assert_eq_text, extract_offset, mark}; |
178 | 178 | ||
179 | use crate::{db::DefDatabase, test_db::TestDB, FunctionId, ModuleDefId}; | 179 | use crate::{db::DefDatabase, test_db::TestDB, FunctionId, ModuleDefId}; |
180 | 180 | ||
@@ -388,7 +388,7 @@ mod tests { | |||
388 | 388 | ||
389 | #[test] | 389 | #[test] |
390 | fn while_let_desugaring() { | 390 | fn while_let_desugaring() { |
391 | covers!(infer_resolve_while_let); | 391 | mark::check!(infer_resolve_while_let); |
392 | do_check_local_name( | 392 | do_check_local_name( |
393 | r#" | 393 | r#" |
394 | fn test() { | 394 | fn test() { |
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index ccb682f9a..807195d25 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -9,12 +9,13 @@ 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 | ||
16 | use crate::{ | 16 | use crate::{ |
17 | attr::Attrs, | 17 | attr::Attrs, |
18 | body::LowerCtx, | ||
18 | db::DefDatabase, | 19 | db::DefDatabase, |
19 | path::{path, AssociatedTypeBinding, GenericArgs, Path}, | 20 | path::{path, AssociatedTypeBinding, GenericArgs, Path}, |
20 | src::HasSource, | 21 | src::HasSource, |
@@ -33,6 +34,7 @@ pub struct FunctionData { | |||
33 | /// True if the first param is `self`. This is relevant to decide whether this | 34 | /// True if the first param is `self`. This is relevant to decide whether this |
34 | /// can be called as a method. | 35 | /// can be called as a method. |
35 | pub has_self_param: bool, | 36 | pub has_self_param: bool, |
37 | pub is_unsafe: bool, | ||
36 | pub visibility: RawVisibility, | 38 | pub visibility: RawVisibility, |
37 | } | 39 | } |
38 | 40 | ||
@@ -40,13 +42,14 @@ impl FunctionData { | |||
40 | pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> { | 42 | pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> { |
41 | let loc = func.lookup(db); | 43 | let loc = func.lookup(db); |
42 | let src = loc.source(db); | 44 | let src = loc.source(db); |
45 | let ctx = LowerCtx::new(db, src.file_id); | ||
43 | let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing); | 46 | let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing); |
44 | let mut params = Vec::new(); | 47 | let mut params = Vec::new(); |
45 | let mut has_self_param = false; | 48 | let mut has_self_param = false; |
46 | if let Some(param_list) = src.value.param_list() { | 49 | if let Some(param_list) = src.value.param_list() { |
47 | if let Some(self_param) = param_list.self_param() { | 50 | if let Some(self_param) = param_list.self_param() { |
48 | let self_type = if let Some(type_ref) = self_param.ascribed_type() { | 51 | let self_type = if let Some(type_ref) = self_param.ascribed_type() { |
49 | TypeRef::from_ast(type_ref) | 52 | TypeRef::from_ast(&ctx, type_ref) |
50 | } else { | 53 | } else { |
51 | let self_type = TypeRef::Path(name![Self].into()); | 54 | let self_type = TypeRef::Path(name![Self].into()); |
52 | match self_param.kind() { | 55 | match self_param.kind() { |
@@ -63,14 +66,14 @@ impl FunctionData { | |||
63 | has_self_param = true; | 66 | has_self_param = true; |
64 | } | 67 | } |
65 | for param in param_list.params() { | 68 | for param in param_list.params() { |
66 | let type_ref = TypeRef::from_ast_opt(param.ascribed_type()); | 69 | let type_ref = TypeRef::from_ast_opt(&ctx, param.ascribed_type()); |
67 | params.push(type_ref); | 70 | params.push(type_ref); |
68 | } | 71 | } |
69 | } | 72 | } |
70 | let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id)); | 73 | let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id)); |
71 | 74 | ||
72 | let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) { | 75 | let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) { |
73 | TypeRef::from_ast(type_ref) | 76 | TypeRef::from_ast(&ctx, type_ref) |
74 | } else { | 77 | } else { |
75 | TypeRef::unit() | 78 | TypeRef::unit() |
76 | }; | 79 | }; |
@@ -83,11 +86,14 @@ impl FunctionData { | |||
83 | ret_type | 86 | ret_type |
84 | }; | 87 | }; |
85 | 88 | ||
89 | let is_unsafe = src.value.unsafe_token().is_some(); | ||
90 | |||
86 | let vis_default = RawVisibility::default_for_container(loc.container); | 91 | let vis_default = RawVisibility::default_for_container(loc.container); |
87 | let visibility = | 92 | let visibility = |
88 | RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility())); | 93 | RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility())); |
89 | 94 | ||
90 | let sig = FunctionData { name, params, ret_type, has_self_param, visibility, attrs }; | 95 | let sig = |
96 | FunctionData { name, params, ret_type, has_self_param, is_unsafe, visibility, attrs }; | ||
91 | Arc::new(sig) | 97 | Arc::new(sig) |
92 | } | 98 | } |
93 | } | 99 | } |
@@ -122,7 +128,8 @@ impl TypeAliasData { | |||
122 | let loc = typ.lookup(db); | 128 | let loc = typ.lookup(db); |
123 | let node = loc.source(db); | 129 | let node = loc.source(db); |
124 | let name = node.value.name().map_or_else(Name::missing, |n| n.as_name()); | 130 | let name = node.value.name().map_or_else(Name::missing, |n| n.as_name()); |
125 | let type_ref = node.value.type_ref().map(TypeRef::from_ast); | 131 | let lower_ctx = LowerCtx::new(db, node.file_id); |
132 | let type_ref = node.value.type_ref().map(|it| TypeRef::from_ast(&lower_ctx, it)); | ||
126 | let vis_default = RawVisibility::default_for_container(loc.container); | 133 | let vis_default = RawVisibility::default_for_container(loc.container); |
127 | let visibility = RawVisibility::from_ast_with_default( | 134 | let visibility = RawVisibility::from_ast_with_default( |
128 | db, | 135 | db, |
@@ -130,7 +137,7 @@ impl TypeAliasData { | |||
130 | node.as_ref().map(|n| n.visibility()), | 137 | node.as_ref().map(|n| n.visibility()), |
131 | ); | 138 | ); |
132 | let bounds = if let Some(bound_list) = node.value.type_bound_list() { | 139 | let bounds = if let Some(bound_list) = node.value.type_bound_list() { |
133 | bound_list.bounds().map(TypeBound::from_ast).collect() | 140 | bound_list.bounds().map(|it| TypeBound::from_ast(&lower_ctx, it)).collect() |
134 | } else { | 141 | } else { |
135 | Vec::new() | 142 | Vec::new() |
136 | }; | 143 | }; |
@@ -147,51 +154,31 @@ pub struct TraitData { | |||
147 | 154 | ||
148 | impl TraitData { | 155 | impl TraitData { |
149 | pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { | 156 | pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { |
150 | let src = tr.lookup(db).source(db); | 157 | let tr_loc = tr.lookup(db); |
158 | let src = tr_loc.source(db); | ||
151 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); | 159 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); |
152 | let auto = src.value.auto_token().is_some(); | 160 | let auto = src.value.auto_token().is_some(); |
153 | let ast_id_map = db.ast_id_map(src.file_id); | 161 | let module_id = tr_loc.container.module(db); |
154 | 162 | ||
155 | let container = AssocContainerId::TraitId(tr); | 163 | let container = AssocContainerId::TraitId(tr); |
156 | let items = if let Some(item_list) = src.value.item_list() { | 164 | let mut items = Vec::new(); |
157 | item_list | 165 | |
158 | .impl_items() | 166 | if let Some(item_list) = src.value.item_list() { |
159 | .map(|item_node| match item_node { | 167 | let mut expander = Expander::new(db, tr_loc.ast_id.file_id, module_id); |
160 | ast::ImplItem::FnDef(it) => { | 168 | items.extend(collect_items( |
161 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); | 169 | db, |
162 | let def = FunctionLoc { | 170 | &mut expander, |
163 | container, | 171 | item_list.assoc_items(), |
164 | ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), | 172 | src.file_id, |
165 | } | 173 | container, |
166 | .intern(db) | 174 | )); |
167 | .into(); | 175 | items.extend(collect_items_in_macros( |
168 | (name, def) | 176 | db, |
169 | } | 177 | &mut expander, |
170 | ast::ImplItem::ConstDef(it) => { | 178 | &src.with_value(item_list), |
171 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); | 179 | container, |
172 | let def = ConstLoc { | 180 | )); |
173 | container, | 181 | } |
174 | ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), | ||
175 | } | ||
176 | .intern(db) | ||
177 | .into(); | ||
178 | (name, def) | ||
179 | } | ||
180 | ast::ImplItem::TypeAliasDef(it) => { | ||
181 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); | ||
182 | let def = TypeAliasLoc { | ||
183 | container, | ||
184 | ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), | ||
185 | } | ||
186 | .intern(db) | ||
187 | .into(); | ||
188 | (name, def) | ||
189 | } | ||
190 | }) | ||
191 | .collect() | ||
192 | } else { | ||
193 | Vec::new() | ||
194 | }; | ||
195 | Arc::new(TraitData { name, items, auto }) | 182 | Arc::new(TraitData { name, items, auto }) |
196 | } | 183 | } |
197 | 184 | ||
@@ -223,29 +210,28 @@ impl ImplData { | |||
223 | let _p = profile("impl_data_query"); | 210 | let _p = profile("impl_data_query"); |
224 | let impl_loc = id.lookup(db); | 211 | let impl_loc = id.lookup(db); |
225 | let src = impl_loc.source(db); | 212 | let src = impl_loc.source(db); |
213 | let lower_ctx = LowerCtx::new(db, src.file_id); | ||
226 | 214 | ||
227 | let target_trait = src.value.target_trait().map(TypeRef::from_ast); | 215 | let target_trait = src.value.target_trait().map(|it| TypeRef::from_ast(&lower_ctx, it)); |
228 | let target_type = TypeRef::from_ast_opt(src.value.target_type()); | 216 | let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type()); |
229 | let is_negative = src.value.excl_token().is_some(); | 217 | let is_negative = src.value.excl_token().is_some(); |
230 | let module_id = impl_loc.container.module(db); | 218 | let module_id = impl_loc.container.module(db); |
219 | let container = AssocContainerId::ImplId(id); | ||
231 | 220 | ||
232 | let mut items = Vec::new(); | 221 | let mut items: Vec<AssocItemId> = Vec::new(); |
233 | 222 | ||
234 | if let Some(item_list) = src.value.item_list() { | 223 | if let Some(item_list) = src.value.item_list() { |
235 | let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); | 224 | let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); |
236 | items.extend(collect_impl_items( | 225 | items.extend( |
237 | db, | 226 | collect_items(db, &mut expander, item_list.assoc_items(), src.file_id, container) |
238 | &mut expander, | 227 | .into_iter() |
239 | item_list.impl_items(), | 228 | .map(|(_, item)| item), |
240 | src.file_id, | 229 | ); |
241 | id, | 230 | items.extend( |
242 | )); | 231 | collect_items_in_macros(db, &mut expander, &src.with_value(item_list), container) |
243 | items.extend(collect_impl_items_in_macros( | 232 | .into_iter() |
244 | db, | 233 | .map(|(_, item)| item), |
245 | &mut expander, | 234 | ); |
246 | &src.with_value(item_list), | ||
247 | id, | ||
248 | )); | ||
249 | } | 235 | } |
250 | 236 | ||
251 | let res = ImplData { target_trait, target_type, items, is_negative }; | 237 | let res = ImplData { target_trait, target_type, items, is_negative }; |
@@ -269,67 +255,90 @@ impl ConstData { | |||
269 | Arc::new(ConstData::new(db, vis_default, node)) | 255 | Arc::new(ConstData::new(db, vis_default, node)) |
270 | } | 256 | } |
271 | 257 | ||
272 | pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<ConstData> { | ||
273 | let node = konst.lookup(db).source(db); | ||
274 | Arc::new(ConstData::new(db, RawVisibility::private(), node)) | ||
275 | } | ||
276 | |||
277 | fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>( | 258 | fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>( |
278 | db: &dyn DefDatabase, | 259 | db: &dyn DefDatabase, |
279 | vis_default: RawVisibility, | 260 | vis_default: RawVisibility, |
280 | node: InFile<N>, | 261 | node: InFile<N>, |
281 | ) -> ConstData { | 262 | ) -> ConstData { |
263 | let ctx = LowerCtx::new(db, node.file_id); | ||
282 | let name = node.value.name().map(|n| n.as_name()); | 264 | let name = node.value.name().map(|n| n.as_name()); |
283 | let type_ref = TypeRef::from_ast_opt(node.value.ascribed_type()); | 265 | let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type()); |
284 | let visibility = | 266 | let visibility = |
285 | RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility())); | 267 | RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility())); |
286 | ConstData { name, type_ref, visibility } | 268 | ConstData { name, type_ref, visibility } |
287 | } | 269 | } |
288 | } | 270 | } |
289 | 271 | ||
290 | fn collect_impl_items_in_macros( | 272 | #[derive(Debug, Clone, PartialEq, Eq)] |
273 | pub struct StaticData { | ||
274 | pub name: Option<Name>, | ||
275 | pub type_ref: TypeRef, | ||
276 | pub visibility: RawVisibility, | ||
277 | pub mutable: bool, | ||
278 | } | ||
279 | |||
280 | impl StaticData { | ||
281 | pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<StaticData> { | ||
282 | let node = konst.lookup(db).source(db); | ||
283 | let ctx = LowerCtx::new(db, node.file_id); | ||
284 | |||
285 | let name = node.value.name().map(|n| n.as_name()); | ||
286 | let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type()); | ||
287 | let mutable = node.value.mut_token().is_some(); | ||
288 | let visibility = RawVisibility::from_ast_with_default( | ||
289 | db, | ||
290 | RawVisibility::private(), | ||
291 | node.map(|n| n.visibility()), | ||
292 | ); | ||
293 | |||
294 | Arc::new(StaticData { name, type_ref, visibility, mutable }) | ||
295 | } | ||
296 | } | ||
297 | |||
298 | fn collect_items_in_macros( | ||
291 | db: &dyn DefDatabase, | 299 | db: &dyn DefDatabase, |
292 | expander: &mut Expander, | 300 | expander: &mut Expander, |
293 | impl_def: &InFile<ast::ItemList>, | 301 | impl_def: &InFile<ast::ItemList>, |
294 | id: ImplId, | 302 | container: AssocContainerId, |
295 | ) -> Vec<AssocItemId> { | 303 | ) -> Vec<(Name, AssocItemId)> { |
296 | let mut res = Vec::new(); | 304 | let mut res = Vec::new(); |
297 | 305 | ||
298 | // We set a limit to protect against infinite recursion | 306 | // We set a limit to protect against infinite recursion |
299 | let limit = 100; | 307 | let limit = 100; |
300 | 308 | ||
301 | for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { | 309 | for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { |
302 | res.extend(collect_impl_items_in_macro(db, expander, m, id, limit)) | 310 | res.extend(collect_items_in_macro(db, expander, m, container, limit)) |
303 | } | 311 | } |
304 | 312 | ||
305 | res | 313 | res |
306 | } | 314 | } |
307 | 315 | ||
308 | fn collect_impl_items_in_macro( | 316 | fn collect_items_in_macro( |
309 | db: &dyn DefDatabase, | 317 | db: &dyn DefDatabase, |
310 | expander: &mut Expander, | 318 | expander: &mut Expander, |
311 | m: ast::MacroCall, | 319 | m: ast::MacroCall, |
312 | id: ImplId, | 320 | container: AssocContainerId, |
313 | limit: usize, | 321 | limit: usize, |
314 | ) -> Vec<AssocItemId> { | 322 | ) -> Vec<(Name, AssocItemId)> { |
315 | if limit == 0 { | 323 | if limit == 0 { |
316 | return Vec::new(); | 324 | return Vec::new(); |
317 | } | 325 | } |
318 | 326 | ||
319 | if let Some((mark, items)) = expander.enter_expand(db, None, m) { | 327 | if let Some((mark, items)) = expander.enter_expand(db, None, m) { |
320 | let items: InFile<ast::MacroItems> = expander.to_source(items); | 328 | let items: InFile<ast::MacroItems> = expander.to_source(items); |
321 | let mut res = collect_impl_items( | 329 | let mut res = collect_items( |
322 | db, | 330 | db, |
323 | expander, | 331 | expander, |
324 | items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), | 332 | items.value.items().filter_map(|it| AssocItem::cast(it.syntax().clone())), |
325 | items.file_id, | 333 | items.file_id, |
326 | id, | 334 | container, |
327 | ); | 335 | ); |
336 | |||
328 | // Recursive collect macros | 337 | // Recursive collect macros |
329 | // Note that ast::ModuleItem do not include ast::MacroCall | 338 | // Note that ast::ModuleItem do not include ast::MacroCall |
330 | // We cannot use ModuleItemOwner::items here | 339 | // We cannot use ModuleItemOwner::items here |
331 | for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { | 340 | for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { |
332 | res.extend(collect_impl_items_in_macro(db, expander, it, id, limit - 1)) | 341 | res.extend(collect_items_in_macro(db, expander, it, container, limit - 1)) |
333 | } | 342 | } |
334 | expander.exit(db, mark); | 343 | expander.exit(db, mark); |
335 | res | 344 | res |
@@ -338,44 +347,38 @@ fn collect_impl_items_in_macro( | |||
338 | } | 347 | } |
339 | } | 348 | } |
340 | 349 | ||
341 | fn collect_impl_items( | 350 | fn collect_items( |
342 | db: &dyn DefDatabase, | 351 | db: &dyn DefDatabase, |
343 | expander: &mut Expander, | 352 | expander: &mut Expander, |
344 | impl_items: impl Iterator<Item = ImplItem>, | 353 | assoc_items: impl Iterator<Item = AssocItem>, |
345 | file_id: crate::HirFileId, | 354 | file_id: crate::HirFileId, |
346 | id: ImplId, | 355 | container: AssocContainerId, |
347 | ) -> Vec<AssocItemId> { | 356 | ) -> Vec<(Name, AssocItemId)> { |
348 | let items = db.ast_id_map(file_id); | 357 | let items = db.ast_id_map(file_id); |
349 | 358 | ||
350 | impl_items | 359 | assoc_items |
351 | .filter_map(|item_node| match item_node { | 360 | .filter_map(|item_node| match item_node { |
352 | ast::ImplItem::FnDef(it) => { | 361 | ast::AssocItem::FnDef(it) => { |
353 | let attrs = expander.parse_attrs(&it); | 362 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); |
354 | if !expander.is_cfg_enabled(&attrs) { | 363 | if !expander.is_cfg_enabled(&it) { |
355 | return None; | 364 | return None; |
356 | } | 365 | } |
357 | let def = FunctionLoc { | 366 | let def = FunctionLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } |
358 | container: AssocContainerId::ImplId(id), | 367 | .intern(db); |
359 | ast_id: AstId::new(file_id, items.ast_id(&it)), | 368 | Some((name, def.into())) |
360 | } | ||
361 | .intern(db); | ||
362 | Some(def.into()) | ||
363 | } | 369 | } |
364 | ast::ImplItem::ConstDef(it) => { | 370 | ast::AssocItem::ConstDef(it) => { |
365 | let def = ConstLoc { | 371 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); |
366 | container: AssocContainerId::ImplId(id), | 372 | let def = ConstLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } |
367 | ast_id: AstId::new(file_id, items.ast_id(&it)), | 373 | .intern(db); |
368 | } | 374 | Some((name, def.into())) |
369 | .intern(db); | ||
370 | Some(def.into()) | ||
371 | } | 375 | } |
372 | ast::ImplItem::TypeAliasDef(it) => { | 376 | ast::AssocItem::TypeAliasDef(it) => { |
373 | let def = TypeAliasLoc { | 377 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); |
374 | container: AssocContainerId::ImplId(id), | 378 | let def = |
375 | ast_id: AstId::new(file_id, items.ast_id(&it)), | 379 | TypeAliasLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } |
376 | } | 380 | .intern(db); |
377 | .intern(db); | 381 | Some((name, def.into())) |
378 | Some(def.into()) | ||
379 | } | 382 | } |
380 | }) | 383 | }) |
381 | .collect() | 384 | .collect() |
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index 5dc7395f5..945a0025e 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! Defines database & queries for name resolution. | 1 | //! Defines database & queries for name resolution. |
2 | use std::sync::Arc; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use hir_expand::{db::AstDatabase, HirFileId}; | 4 | use hir_expand::{db::AstDatabase, name::Name, HirFileId}; |
5 | use ra_db::{salsa, CrateId, SourceDatabase, Upcast}; | 5 | use ra_db::{salsa, CrateId, SourceDatabase, Upcast}; |
6 | use ra_prof::profile; | 6 | use ra_prof::profile; |
7 | use ra_syntax::SmolStr; | 7 | use ra_syntax::SmolStr; |
@@ -10,11 +10,15 @@ use crate::{ | |||
10 | adt::{EnumData, StructData}, | 10 | adt::{EnumData, StructData}, |
11 | attr::Attrs, | 11 | attr::Attrs, |
12 | body::{scope::ExprScopes, Body, BodySourceMap}, | 12 | body::{scope::ExprScopes, Body, BodySourceMap}, |
13 | data::{ConstData, FunctionData, ImplData, TraitData, TypeAliasData}, | 13 | data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, |
14 | docs::Documentation, | 14 | docs::Documentation, |
15 | find_path, | ||
15 | generics::GenericParams, | 16 | generics::GenericParams, |
17 | item_scope::ItemInNs, | ||
16 | lang_item::{LangItemTarget, LangItems}, | 18 | lang_item::{LangItemTarget, LangItems}, |
17 | nameres::{raw::RawItems, CrateDefMap}, | 19 | nameres::{raw::RawItems, CrateDefMap}, |
20 | path::ModPath, | ||
21 | visibility::Visibility, | ||
18 | AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, | 22 | AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, |
19 | GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId, | 23 | GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId, |
20 | TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, | 24 | TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, |
@@ -77,8 +81,8 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
77 | #[salsa::invoke(ConstData::const_data_query)] | 81 | #[salsa::invoke(ConstData::const_data_query)] |
78 | fn const_data(&self, konst: ConstId) -> Arc<ConstData>; | 82 | fn const_data(&self, konst: ConstId) -> Arc<ConstData>; |
79 | 83 | ||
80 | #[salsa::invoke(ConstData::static_data_query)] | 84 | #[salsa::invoke(StaticData::static_data_query)] |
81 | fn static_data(&self, konst: StaticId) -> Arc<ConstData>; | 85 | fn static_data(&self, konst: StaticId) -> Arc<StaticData>; |
82 | 86 | ||
83 | #[salsa::invoke(Body::body_with_source_map_query)] | 87 | #[salsa::invoke(Body::body_with_source_map_query)] |
84 | fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>); | 88 | fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>); |
@@ -108,6 +112,16 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
108 | // Remove this query completely, in favor of `Attrs::docs` method | 112 | // Remove this query completely, in favor of `Attrs::docs` method |
109 | #[salsa::invoke(Documentation::documentation_query)] | 113 | #[salsa::invoke(Documentation::documentation_query)] |
110 | fn documentation(&self, def: AttrDefId) -> Option<Documentation>; | 114 | fn documentation(&self, def: AttrDefId) -> Option<Documentation>; |
115 | |||
116 | #[salsa::invoke(find_path::importable_locations_of_query)] | ||
117 | fn importable_locations_of( | ||
118 | &self, | ||
119 | item: ItemInNs, | ||
120 | krate: CrateId, | ||
121 | ) -> Arc<[(ModuleId, Name, Visibility)]>; | ||
122 | |||
123 | #[salsa::invoke(find_path::find_path_inner_query)] | ||
124 | fn find_path_inner(&self, item: ItemInNs, from: ModuleId, max_len: usize) -> Option<ModPath>; | ||
111 | } | 125 | } |
112 | 126 | ||
113 | fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<CrateDefMap> { | 127 | fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<CrateDefMap> { |
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs index aad12e123..ca49b26d1 100644 --- a/crates/ra_hir_def/src/expr.rs +++ b/crates/ra_hir_def/src/expr.rs | |||
@@ -19,7 +19,7 @@ use ra_syntax::ast::RangeOp; | |||
19 | use crate::{ | 19 | use crate::{ |
20 | builtin_type::{BuiltinFloat, BuiltinInt}, | 20 | builtin_type::{BuiltinFloat, BuiltinInt}, |
21 | path::{GenericArgs, Path}, | 21 | path::{GenericArgs, Path}, |
22 | type_ref::{Mutability, TypeRef}, | 22 | type_ref::{Mutability, Rawness, TypeRef}, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | pub type ExprId = Idx<Expr>; | 25 | pub type ExprId = Idx<Expr>; |
@@ -52,18 +52,22 @@ pub enum Expr { | |||
52 | Block { | 52 | Block { |
53 | statements: Vec<Statement>, | 53 | statements: Vec<Statement>, |
54 | tail: Option<ExprId>, | 54 | tail: Option<ExprId>, |
55 | label: Option<Name>, | ||
55 | }, | 56 | }, |
56 | Loop { | 57 | Loop { |
57 | body: ExprId, | 58 | body: ExprId, |
59 | label: Option<Name>, | ||
58 | }, | 60 | }, |
59 | While { | 61 | While { |
60 | condition: ExprId, | 62 | condition: ExprId, |
61 | body: ExprId, | 63 | body: ExprId, |
64 | label: Option<Name>, | ||
62 | }, | 65 | }, |
63 | For { | 66 | For { |
64 | iterable: ExprId, | 67 | iterable: ExprId, |
65 | pat: PatId, | 68 | pat: PatId, |
66 | body: ExprId, | 69 | body: ExprId, |
70 | label: Option<Name>, | ||
67 | }, | 71 | }, |
68 | Call { | 72 | Call { |
69 | callee: ExprId, | 73 | callee: ExprId, |
@@ -79,9 +83,12 @@ pub enum Expr { | |||
79 | expr: ExprId, | 83 | expr: ExprId, |
80 | arms: Vec<MatchArm>, | 84 | arms: Vec<MatchArm>, |
81 | }, | 85 | }, |
82 | Continue, | 86 | Continue { |
87 | label: Option<Name>, | ||
88 | }, | ||
83 | Break { | 89 | Break { |
84 | expr: Option<ExprId>, | 90 | expr: Option<ExprId>, |
91 | label: Option<Name>, | ||
85 | }, | 92 | }, |
86 | Return { | 93 | Return { |
87 | expr: Option<ExprId>, | 94 | expr: Option<ExprId>, |
@@ -101,12 +108,16 @@ pub enum Expr { | |||
101 | Try { | 108 | Try { |
102 | expr: ExprId, | 109 | expr: ExprId, |
103 | }, | 110 | }, |
111 | TryBlock { | ||
112 | body: ExprId, | ||
113 | }, | ||
104 | Cast { | 114 | Cast { |
105 | expr: ExprId, | 115 | expr: ExprId, |
106 | type_ref: TypeRef, | 116 | type_ref: TypeRef, |
107 | }, | 117 | }, |
108 | Ref { | 118 | Ref { |
109 | expr: ExprId, | 119 | expr: ExprId, |
120 | rawness: Rawness, | ||
110 | mutability: Mutability, | 121 | mutability: Mutability, |
111 | }, | 122 | }, |
112 | Box { | 123 | Box { |
@@ -221,7 +232,7 @@ impl Expr { | |||
221 | f(*else_branch); | 232 | f(*else_branch); |
222 | } | 233 | } |
223 | } | 234 | } |
224 | Expr::Block { statements, tail } => { | 235 | Expr::Block { statements, tail, .. } => { |
225 | for stmt in statements { | 236 | for stmt in statements { |
226 | match stmt { | 237 | match stmt { |
227 | Statement::Let { initializer, .. } => { | 238 | Statement::Let { initializer, .. } => { |
@@ -236,8 +247,9 @@ impl Expr { | |||
236 | f(*expr); | 247 | f(*expr); |
237 | } | 248 | } |
238 | } | 249 | } |
239 | Expr::Loop { body } => f(*body), | 250 | Expr::TryBlock { body } => f(*body), |
240 | Expr::While { condition, body } => { | 251 | Expr::Loop { body, .. } => f(*body), |
252 | Expr::While { condition, body, .. } => { | ||
241 | f(*condition); | 253 | f(*condition); |
242 | f(*body); | 254 | f(*body); |
243 | } | 255 | } |
@@ -263,8 +275,8 @@ impl Expr { | |||
263 | f(arm.expr); | 275 | f(arm.expr); |
264 | } | 276 | } |
265 | } | 277 | } |
266 | Expr::Continue => {} | 278 | Expr::Continue { .. } => {} |
267 | Expr::Break { expr } | Expr::Return { expr } => { | 279 | Expr::Break { expr, .. } | Expr::Return { expr } => { |
268 | if let Some(expr) = expr { | 280 | if let Some(expr) = expr { |
269 | f(*expr); | 281 | f(*expr); |
270 | } | 282 | } |
diff --git a/crates/ra_hir_def/src/find_path.rs b/crates/ra_hir_def/src/find_path.rs index 70dcb03e6..4db798473 100644 --- a/crates/ra_hir_def/src/find_path.rs +++ b/crates/ra_hir_def/src/find_path.rs | |||
@@ -1,5 +1,11 @@ | |||
1 | //! An algorithm to find a path to refer to a certain item. | 1 | //! An algorithm to find a path to refer to a certain item. |
2 | 2 | ||
3 | use std::sync::Arc; | ||
4 | |||
5 | use hir_expand::name::{known, AsName, Name}; | ||
6 | use ra_prof::profile; | ||
7 | use test_utils::mark; | ||
8 | |||
3 | use crate::{ | 9 | use crate::{ |
4 | db::DefDatabase, | 10 | db::DefDatabase, |
5 | item_scope::ItemInNs, | 11 | item_scope::ItemInNs, |
@@ -7,25 +13,28 @@ use crate::{ | |||
7 | visibility::Visibility, | 13 | visibility::Visibility, |
8 | CrateId, ModuleDefId, ModuleId, | 14 | CrateId, ModuleDefId, ModuleId, |
9 | }; | 15 | }; |
10 | use hir_expand::name::{known, AsName, Name}; | 16 | |
11 | use test_utils::tested_by; | 17 | // FIXME: handle local items |
18 | |||
19 | /// Find a path that can be used to refer to a certain item. This can depend on | ||
20 | /// *from where* you're referring to the item, hence the `from` parameter. | ||
21 | pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> { | ||
22 | let _p = profile("find_path"); | ||
23 | db.find_path_inner(item, from, MAX_PATH_LEN) | ||
24 | } | ||
12 | 25 | ||
13 | const MAX_PATH_LEN: usize = 15; | 26 | const MAX_PATH_LEN: usize = 15; |
14 | 27 | ||
15 | impl ModPath { | 28 | impl ModPath { |
16 | fn starts_with_std(&self) -> bool { | 29 | fn starts_with_std(&self) -> bool { |
17 | self.segments.first().filter(|&first_segment| first_segment == &known::std).is_some() | 30 | self.segments.first() == Some(&known::std) |
18 | } | 31 | } |
19 | 32 | ||
20 | // When std library is present, paths starting with `std::` | 33 | // When std library is present, paths starting with `std::` |
21 | // should be preferred over paths starting with `core::` and `alloc::` | 34 | // should be preferred over paths starting with `core::` and `alloc::` |
22 | fn can_start_with_std(&self) -> bool { | 35 | fn can_start_with_std(&self) -> bool { |
23 | self.segments | 36 | let first_segment = self.segments.first(); |
24 | .first() | 37 | first_segment == Some(&known::alloc) || first_segment == Some(&known::core) |
25 | .filter(|&first_segment| { | ||
26 | first_segment == &known::alloc || first_segment == &known::core | ||
27 | }) | ||
28 | .is_some() | ||
29 | } | 38 | } |
30 | 39 | ||
31 | fn len(&self) -> usize { | 40 | fn len(&self) -> usize { |
@@ -40,15 +49,7 @@ impl ModPath { | |||
40 | } | 49 | } |
41 | } | 50 | } |
42 | 51 | ||
43 | // FIXME: handle local items | 52 | pub(crate) fn find_path_inner_query( |
44 | |||
45 | /// Find a path that can be used to refer to a certain item. This can depend on | ||
46 | /// *from where* you're referring to the item, hence the `from` parameter. | ||
47 | pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> { | ||
48 | find_path_inner(db, item, from, MAX_PATH_LEN) | ||
49 | } | ||
50 | |||
51 | fn find_path_inner( | ||
52 | db: &dyn DefDatabase, | 53 | db: &dyn DefDatabase, |
53 | item: ItemInNs, | 54 | item: ItemInNs, |
54 | from: ModuleId, | 55 | from: ModuleId, |
@@ -139,8 +140,7 @@ fn find_path_inner( | |||
139 | let mut best_path = None; | 140 | let mut best_path = None; |
140 | let mut best_path_len = max_len; | 141 | let mut best_path_len = max_len; |
141 | for (module_id, name) in importable_locations { | 142 | for (module_id, name) in importable_locations { |
142 | let mut path = match find_path_inner( | 143 | let mut path = match db.find_path_inner( |
143 | db, | ||
144 | ItemInNs::Types(ModuleDefId::ModuleId(module_id)), | 144 | ItemInNs::Types(ModuleDefId::ModuleId(module_id)), |
145 | from, | 145 | from, |
146 | best_path_len - 1, | 146 | best_path_len - 1, |
@@ -163,17 +163,19 @@ fn find_path_inner( | |||
163 | 163 | ||
164 | fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) -> ModPath { | 164 | fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) -> ModPath { |
165 | if old_path.starts_with_std() && new_path.can_start_with_std() { | 165 | if old_path.starts_with_std() && new_path.can_start_with_std() { |
166 | tested_by!(prefer_std_paths); | ||
167 | if prefer_no_std { | 166 | if prefer_no_std { |
167 | mark::hit!(prefer_no_std_paths); | ||
168 | new_path | 168 | new_path |
169 | } else { | 169 | } else { |
170 | mark::hit!(prefer_std_paths); | ||
170 | old_path | 171 | old_path |
171 | } | 172 | } |
172 | } else if new_path.starts_with_std() && old_path.can_start_with_std() { | 173 | } else if new_path.starts_with_std() && old_path.can_start_with_std() { |
173 | tested_by!(prefer_std_paths); | ||
174 | if prefer_no_std { | 174 | if prefer_no_std { |
175 | mark::hit!(prefer_no_std_paths); | ||
175 | old_path | 176 | old_path |
176 | } else { | 177 | } else { |
178 | mark::hit!(prefer_std_paths); | ||
177 | new_path | 179 | new_path |
178 | } | 180 | } |
179 | } else if new_path.len() < old_path.len() { | 181 | } else if new_path.len() < old_path.len() { |
@@ -198,7 +200,7 @@ fn find_importable_locations( | |||
198 | .chain(crate_graph[from.krate].dependencies.iter().map(|dep| dep.crate_id)) | 200 | .chain(crate_graph[from.krate].dependencies.iter().map(|dep| dep.crate_id)) |
199 | { | 201 | { |
200 | result.extend( | 202 | result.extend( |
201 | importable_locations_in_crate(db, item, krate) | 203 | db.importable_locations_of(item, krate) |
202 | .iter() | 204 | .iter() |
203 | .filter(|(_, _, vis)| vis.is_visible_from(db, from)) | 205 | .filter(|(_, _, vis)| vis.is_visible_from(db, from)) |
204 | .map(|(m, n, _)| (*m, n.clone())), | 206 | .map(|(m, n, _)| (*m, n.clone())), |
@@ -213,11 +215,12 @@ fn find_importable_locations( | |||
213 | /// | 215 | /// |
214 | /// Note that the crate doesn't need to be the one in which the item is defined; | 216 | /// Note that the crate doesn't need to be the one in which the item is defined; |
215 | /// it might be re-exported in other crates. | 217 | /// it might be re-exported in other crates. |
216 | fn importable_locations_in_crate( | 218 | pub(crate) fn importable_locations_of_query( |
217 | db: &dyn DefDatabase, | 219 | db: &dyn DefDatabase, |
218 | item: ItemInNs, | 220 | item: ItemInNs, |
219 | krate: CrateId, | 221 | krate: CrateId, |
220 | ) -> Vec<(ModuleId, Name, Visibility)> { | 222 | ) -> Arc<[(ModuleId, Name, Visibility)]> { |
223 | let _p = profile("importable_locations_of_query"); | ||
221 | let def_map = db.crate_def_map(krate); | 224 | let def_map = db.crate_def_map(krate); |
222 | let mut result = Vec::new(); | 225 | let mut result = Vec::new(); |
223 | for (local_id, data) in def_map.modules.iter() { | 226 | for (local_id, data) in def_map.modules.iter() { |
@@ -243,17 +246,20 @@ fn importable_locations_in_crate( | |||
243 | result.push((ModuleId { krate, local_id }, name.clone(), vis)); | 246 | result.push((ModuleId { krate, local_id }, name.clone(), vis)); |
244 | } | 247 | } |
245 | } | 248 | } |
246 | result | 249 | |
250 | Arc::from(result) | ||
247 | } | 251 | } |
248 | 252 | ||
249 | #[cfg(test)] | 253 | #[cfg(test)] |
250 | mod tests { | 254 | mod tests { |
251 | use super::*; | ||
252 | use crate::test_db::TestDB; | ||
253 | use hir_expand::hygiene::Hygiene; | 255 | use hir_expand::hygiene::Hygiene; |
254 | use ra_db::fixture::WithFixture; | 256 | use ra_db::fixture::WithFixture; |
255 | use ra_syntax::ast::AstNode; | 257 | use ra_syntax::ast::AstNode; |
256 | use test_utils::covers; | 258 | use test_utils::mark; |
259 | |||
260 | use crate::test_db::TestDB; | ||
261 | |||
262 | use super::*; | ||
257 | 263 | ||
258 | /// `code` needs to contain a cursor marker; checks that `find_path` for the | 264 | /// `code` needs to contain a cursor marker; checks that `find_path` for the |
259 | /// item the `path` refers to returns that same path when called from the | 265 | /// item the `path` refers to returns that same path when called from the |
@@ -508,7 +514,7 @@ mod tests { | |||
508 | 514 | ||
509 | #[test] | 515 | #[test] |
510 | fn prefer_std_paths_over_alloc() { | 516 | fn prefer_std_paths_over_alloc() { |
511 | covers!(prefer_std_paths); | 517 | mark::check!(prefer_std_paths); |
512 | let code = r#" | 518 | let code = r#" |
513 | //- /main.rs crate:main deps:alloc,std | 519 | //- /main.rs crate:main deps:alloc,std |
514 | <|> | 520 | <|> |
@@ -527,51 +533,50 @@ mod tests { | |||
527 | } | 533 | } |
528 | 534 | ||
529 | #[test] | 535 | #[test] |
530 | fn prefer_alloc_paths_over_std() { | 536 | fn prefer_core_paths_over_std() { |
531 | covers!(prefer_std_paths); | 537 | mark::check!(prefer_no_std_paths); |
532 | let code = r#" | 538 | let code = r#" |
533 | //- /main.rs crate:main deps:alloc,std | 539 | //- /main.rs crate:main deps:core,std |
534 | #![no_std] | 540 | #![no_std] |
535 | 541 | ||
536 | <|> | 542 | <|> |
537 | 543 | ||
538 | //- /std.rs crate:std deps:alloc | 544 | //- /std.rs crate:std deps:core |
539 | 545 | ||
540 | pub mod sync { | 546 | pub mod fmt { |
541 | pub use alloc::sync::Arc; | 547 | pub use core::fmt::Error; |
542 | } | 548 | } |
543 | 549 | ||
544 | //- /zzz.rs crate:alloc | 550 | //- /zzz.rs crate:core |
545 | 551 | ||
546 | pub mod sync { | 552 | pub mod fmt { |
547 | pub struct Arc; | 553 | pub struct Error; |
548 | } | 554 | } |
549 | "#; | 555 | "#; |
550 | check_found_path(code, "alloc::sync::Arc"); | 556 | check_found_path(code, "core::fmt::Error"); |
551 | } | 557 | } |
552 | 558 | ||
553 | #[test] | 559 | #[test] |
554 | fn prefer_core_paths_over_std() { | 560 | fn prefer_alloc_paths_over_std() { |
555 | covers!(prefer_std_paths); | ||
556 | let code = r#" | 561 | let code = r#" |
557 | //- /main.rs crate:main deps:core,std | 562 | //- /main.rs crate:main deps:alloc,std |
558 | #![no_std] | 563 | #![no_std] |
559 | 564 | ||
560 | <|> | 565 | <|> |
561 | 566 | ||
562 | //- /std.rs crate:std deps:core | 567 | //- /std.rs crate:std deps:alloc |
563 | 568 | ||
564 | pub mod fmt { | 569 | pub mod sync { |
565 | pub use core::fmt::Error; | 570 | pub use alloc::sync::Arc; |
566 | } | 571 | } |
567 | 572 | ||
568 | //- /zzz.rs crate:core | 573 | //- /zzz.rs crate:alloc |
569 | 574 | ||
570 | pub mod fmt { | 575 | pub mod sync { |
571 | pub struct Error; | 576 | pub struct Arc; |
572 | } | 577 | } |
573 | "#; | 578 | "#; |
574 | check_found_path(code, "core::fmt::Error"); | 579 | check_found_path(code, "alloc::sync::Arc"); |
575 | } | 580 | } |
576 | 581 | ||
577 | #[test] | 582 | #[test] |
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index d850244c4..09a5241f7 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs | |||
@@ -15,6 +15,7 @@ use ra_prof::profile; | |||
15 | use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; | 15 | use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; |
16 | 16 | ||
17 | use crate::{ | 17 | use crate::{ |
18 | body::LowerCtx, | ||
18 | child_by_source::ChildBySource, | 19 | child_by_source::ChildBySource, |
19 | db::DefDatabase, | 20 | db::DefDatabase, |
20 | dyn_map::DynMap, | 21 | dyn_map::DynMap, |
@@ -80,11 +81,13 @@ impl GenericParams { | |||
80 | fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { | 81 | fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { |
81 | let mut generics = GenericParams { types: Arena::default(), where_predicates: Vec::new() }; | 82 | let mut generics = GenericParams { types: Arena::default(), where_predicates: Vec::new() }; |
82 | let mut sm = ArenaMap::default(); | 83 | let mut sm = ArenaMap::default(); |
84 | |||
83 | // FIXME: add `: Sized` bound for everything except for `Self` in traits | 85 | // FIXME: add `: Sized` bound for everything except for `Self` in traits |
84 | let file_id = match def { | 86 | let file_id = match def { |
85 | GenericDefId::FunctionId(it) => { | 87 | GenericDefId::FunctionId(it) => { |
86 | let src = it.lookup(db).source(db); | 88 | let src = it.lookup(db).source(db); |
87 | generics.fill(&mut sm, &src.value); | 89 | let lower_ctx = LowerCtx::new(db, src.file_id); |
90 | generics.fill(&lower_ctx, &mut sm, &src.value); | ||
88 | // lower `impl Trait` in arguments | 91 | // lower `impl Trait` in arguments |
89 | let data = db.function_data(it); | 92 | let data = db.function_data(it); |
90 | for param in &data.params { | 93 | for param in &data.params { |
@@ -94,21 +97,25 @@ impl GenericParams { | |||
94 | } | 97 | } |
95 | GenericDefId::AdtId(AdtId::StructId(it)) => { | 98 | GenericDefId::AdtId(AdtId::StructId(it)) => { |
96 | let src = it.lookup(db).source(db); | 99 | let src = it.lookup(db).source(db); |
97 | generics.fill(&mut sm, &src.value); | 100 | let lower_ctx = LowerCtx::new(db, src.file_id); |
101 | generics.fill(&lower_ctx, &mut sm, &src.value); | ||
98 | src.file_id | 102 | src.file_id |
99 | } | 103 | } |
100 | GenericDefId::AdtId(AdtId::UnionId(it)) => { | 104 | GenericDefId::AdtId(AdtId::UnionId(it)) => { |
101 | let src = it.lookup(db).source(db); | 105 | let src = it.lookup(db).source(db); |
102 | generics.fill(&mut sm, &src.value); | 106 | let lower_ctx = LowerCtx::new(db, src.file_id); |
107 | generics.fill(&lower_ctx, &mut sm, &src.value); | ||
103 | src.file_id | 108 | src.file_id |
104 | } | 109 | } |
105 | GenericDefId::AdtId(AdtId::EnumId(it)) => { | 110 | GenericDefId::AdtId(AdtId::EnumId(it)) => { |
106 | let src = it.lookup(db).source(db); | 111 | let src = it.lookup(db).source(db); |
107 | generics.fill(&mut sm, &src.value); | 112 | let lower_ctx = LowerCtx::new(db, src.file_id); |
113 | generics.fill(&lower_ctx, &mut sm, &src.value); | ||
108 | src.file_id | 114 | src.file_id |
109 | } | 115 | } |
110 | GenericDefId::TraitId(it) => { | 116 | GenericDefId::TraitId(it) => { |
111 | let src = it.lookup(db).source(db); | 117 | let src = it.lookup(db).source(db); |
118 | let lower_ctx = LowerCtx::new(db, src.file_id); | ||
112 | 119 | ||
113 | // traits get the Self type as an implicit first type parameter | 120 | // traits get the Self type as an implicit first type parameter |
114 | let self_param_id = generics.types.alloc(TypeParamData { | 121 | let self_param_id = generics.types.alloc(TypeParamData { |
@@ -120,14 +127,16 @@ impl GenericParams { | |||
120 | // add super traits as bounds on Self | 127 | // add super traits as bounds on Self |
121 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar | 128 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar |
122 | let self_param = TypeRef::Path(name![Self].into()); | 129 | let self_param = TypeRef::Path(name![Self].into()); |
123 | generics.fill_bounds(&src.value, self_param); | 130 | generics.fill_bounds(&lower_ctx, &src.value, self_param); |
124 | 131 | ||
125 | generics.fill(&mut sm, &src.value); | 132 | generics.fill(&lower_ctx, &mut sm, &src.value); |
126 | src.file_id | 133 | src.file_id |
127 | } | 134 | } |
128 | GenericDefId::TypeAliasId(it) => { | 135 | GenericDefId::TypeAliasId(it) => { |
129 | let src = it.lookup(db).source(db); | 136 | let src = it.lookup(db).source(db); |
130 | generics.fill(&mut sm, &src.value); | 137 | let lower_ctx = LowerCtx::new(db, src.file_id); |
138 | |||
139 | generics.fill(&lower_ctx, &mut sm, &src.value); | ||
131 | src.file_id | 140 | src.file_id |
132 | } | 141 | } |
133 | // Note that we don't add `Self` here: in `impl`s, `Self` is not a | 142 | // Note that we don't add `Self` here: in `impl`s, `Self` is not a |
@@ -135,7 +144,9 @@ impl GenericParams { | |||
135 | // type, so this is handled by the resolver. | 144 | // type, so this is handled by the resolver. |
136 | GenericDefId::ImplId(it) => { | 145 | GenericDefId::ImplId(it) => { |
137 | let src = it.lookup(db).source(db); | 146 | let src = it.lookup(db).source(db); |
138 | generics.fill(&mut sm, &src.value); | 147 | let lower_ctx = LowerCtx::new(db, src.file_id); |
148 | |||
149 | generics.fill(&lower_ctx, &mut sm, &src.value); | ||
139 | src.file_id | 150 | src.file_id |
140 | } | 151 | } |
141 | // We won't be using this ID anyway | 152 | // We won't be using this ID anyway |
@@ -145,28 +156,38 @@ impl GenericParams { | |||
145 | (generics, InFile::new(file_id, sm)) | 156 | (generics, InFile::new(file_id, sm)) |
146 | } | 157 | } |
147 | 158 | ||
148 | fn fill(&mut self, sm: &mut SourceMap, node: &dyn TypeParamsOwner) { | 159 | fn fill(&mut self, lower_ctx: &LowerCtx, sm: &mut SourceMap, node: &dyn TypeParamsOwner) { |
149 | if let Some(params) = node.type_param_list() { | 160 | if let Some(params) = node.type_param_list() { |
150 | self.fill_params(sm, params) | 161 | self.fill_params(lower_ctx, sm, params) |
151 | } | 162 | } |
152 | if let Some(where_clause) = node.where_clause() { | 163 | if let Some(where_clause) = node.where_clause() { |
153 | self.fill_where_predicates(where_clause); | 164 | self.fill_where_predicates(lower_ctx, where_clause); |
154 | } | 165 | } |
155 | } | 166 | } |
156 | 167 | ||
157 | fn fill_bounds(&mut self, node: &dyn ast::TypeBoundsOwner, type_ref: TypeRef) { | 168 | fn fill_bounds( |
169 | &mut self, | ||
170 | lower_ctx: &LowerCtx, | ||
171 | node: &dyn ast::TypeBoundsOwner, | ||
172 | type_ref: TypeRef, | ||
173 | ) { | ||
158 | for bound in | 174 | for bound in |
159 | node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) | 175 | node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) |
160 | { | 176 | { |
161 | self.add_where_predicate_from_bound(bound, type_ref.clone()); | 177 | self.add_where_predicate_from_bound(lower_ctx, bound, type_ref.clone()); |
162 | } | 178 | } |
163 | } | 179 | } |
164 | 180 | ||
165 | fn fill_params(&mut self, sm: &mut SourceMap, params: ast::TypeParamList) { | 181 | fn fill_params( |
182 | &mut self, | ||
183 | lower_ctx: &LowerCtx, | ||
184 | sm: &mut SourceMap, | ||
185 | params: ast::TypeParamList, | ||
186 | ) { | ||
166 | for type_param in params.type_params() { | 187 | for type_param in params.type_params() { |
167 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); | 188 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); |
168 | // FIXME: Use `Path::from_src` | 189 | // FIXME: Use `Path::from_src` |
169 | let default = type_param.default_type().map(TypeRef::from_ast); | 190 | let default = type_param.default_type().map(|it| TypeRef::from_ast(lower_ctx, it)); |
170 | let param = TypeParamData { | 191 | let param = TypeParamData { |
171 | name: Some(name.clone()), | 192 | name: Some(name.clone()), |
172 | default, | 193 | default, |
@@ -176,29 +197,34 @@ impl GenericParams { | |||
176 | sm.insert(param_id, Either::Right(type_param.clone())); | 197 | sm.insert(param_id, Either::Right(type_param.clone())); |
177 | 198 | ||
178 | let type_ref = TypeRef::Path(name.into()); | 199 | let type_ref = TypeRef::Path(name.into()); |
179 | self.fill_bounds(&type_param, type_ref); | 200 | self.fill_bounds(&lower_ctx, &type_param, type_ref); |
180 | } | 201 | } |
181 | } | 202 | } |
182 | 203 | ||
183 | fn fill_where_predicates(&mut self, where_clause: ast::WhereClause) { | 204 | fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx, where_clause: ast::WhereClause) { |
184 | for pred in where_clause.predicates() { | 205 | for pred in where_clause.predicates() { |
185 | let type_ref = match pred.type_ref() { | 206 | let type_ref = match pred.type_ref() { |
186 | Some(type_ref) => type_ref, | 207 | Some(type_ref) => type_ref, |
187 | None => continue, | 208 | None => continue, |
188 | }; | 209 | }; |
189 | let type_ref = TypeRef::from_ast(type_ref); | 210 | let type_ref = TypeRef::from_ast(lower_ctx, type_ref); |
190 | for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { | 211 | for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { |
191 | self.add_where_predicate_from_bound(bound, type_ref.clone()); | 212 | self.add_where_predicate_from_bound(lower_ctx, bound, type_ref.clone()); |
192 | } | 213 | } |
193 | } | 214 | } |
194 | } | 215 | } |
195 | 216 | ||
196 | fn add_where_predicate_from_bound(&mut self, bound: ast::TypeBound, type_ref: TypeRef) { | 217 | fn add_where_predicate_from_bound( |
218 | &mut self, | ||
219 | lower_ctx: &LowerCtx, | ||
220 | bound: ast::TypeBound, | ||
221 | type_ref: TypeRef, | ||
222 | ) { | ||
197 | if bound.question_token().is_some() { | 223 | if bound.question_token().is_some() { |
198 | // FIXME: remove this bound | 224 | // FIXME: remove this bound |
199 | return; | 225 | return; |
200 | } | 226 | } |
201 | let bound = TypeBound::from_ast(bound); | 227 | let bound = TypeBound::from_ast(lower_ctx, bound); |
202 | self.where_predicates | 228 | self.where_predicates |
203 | .push(WherePredicate { target: WherePredicateTarget::TypeRef(type_ref), bound }); | 229 | .push(WherePredicate { target: WherePredicateTarget::TypeRef(type_ref), bound }); |
204 | } | 230 | } |
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/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs index d96ac8c0a..3516784b8 100644 --- a/crates/ra_hir_def/src/lang_item.rs +++ b/crates/ra_hir_def/src/lang_item.rs | |||
@@ -73,8 +73,8 @@ pub struct LangItems { | |||
73 | } | 73 | } |
74 | 74 | ||
75 | impl LangItems { | 75 | impl LangItems { |
76 | pub fn target<'a>(&'a self, item: &str) -> Option<&'a LangItemTarget> { | 76 | pub fn target(&self, item: &str) -> Option<LangItemTarget> { |
77 | self.items.get(item) | 77 | self.items.get(item).copied() |
78 | } | 78 | } |
79 | 79 | ||
80 | /// Salsa query. This will look for lang items in a specific crate. | 80 | /// Salsa query. This will look for lang items in a specific crate. |
@@ -163,9 +163,13 @@ impl LangItems { | |||
163 | ) where | 163 | ) where |
164 | T: Into<AttrDefId> + Copy, | 164 | T: Into<AttrDefId> + Copy, |
165 | { | 165 | { |
166 | let attrs = db.attrs(item.into()); | 166 | if let Some(lang_item_name) = lang_attr(db, item) { |
167 | if let Some(lang_item_name) = attrs.by_key("lang").string_value() { | 167 | self.items.entry(lang_item_name).or_insert_with(|| constructor(item)); |
168 | self.items.entry(lang_item_name.clone()).or_insert_with(|| constructor(item)); | ||
169 | } | 168 | } |
170 | } | 169 | } |
171 | } | 170 | } |
171 | |||
172 | pub fn lang_attr(db: &dyn DefDatabase, item: impl Into<AttrDefId> + Copy) -> Option<SmolStr> { | ||
173 | let attrs = db.attrs(item.into()); | ||
174 | attrs.by_key("lang").string_value().cloned() | ||
175 | } | ||
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 518772e8a..5325a2760 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -46,8 +46,6 @@ pub mod find_path; | |||
46 | 46 | ||
47 | #[cfg(test)] | 47 | #[cfg(test)] |
48 | mod test_db; | 48 | mod test_db; |
49 | #[cfg(test)] | ||
50 | mod marks; | ||
51 | 49 | ||
52 | use std::hash::Hash; | 50 | use std::hash::Hash; |
53 | 51 | ||
diff --git a/crates/ra_hir_def/src/marks.rs b/crates/ra_hir_def/src/marks.rs deleted file mode 100644 index daa49d5f1..000000000 --- a/crates/ra_hir_def/src/marks.rs +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | //! See test_utils/src/marks.rs | ||
2 | |||
3 | test_utils::marks!( | ||
4 | bogus_paths | ||
5 | name_res_works_for_broken_modules | ||
6 | can_import_enum_variant | ||
7 | glob_enum | ||
8 | glob_enum_group | ||
9 | glob_across_crates | ||
10 | std_prelude | ||
11 | macro_rules_from_other_crates_are_visible_with_macro_use | ||
12 | prelude_is_macro_use | ||
13 | macro_dollar_crate_self | ||
14 | macro_dollar_crate_other | ||
15 | infer_resolve_while_let | ||
16 | prefer_std_paths | ||
17 | ); | ||
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 98c74fe25..353a31ad4 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -14,7 +14,7 @@ use ra_cfg::CfgOptions; | |||
14 | use ra_db::{CrateId, FileId, ProcMacroId}; | 14 | use ra_db::{CrateId, FileId, ProcMacroId}; |
15 | use ra_syntax::ast; | 15 | use ra_syntax::ast; |
16 | use rustc_hash::FxHashMap; | 16 | use rustc_hash::FxHashMap; |
17 | use test_utils::tested_by; | 17 | use test_utils::mark; |
18 | 18 | ||
19 | use crate::{ | 19 | use crate::{ |
20 | attr::Attrs, | 20 | attr::Attrs, |
@@ -204,6 +204,7 @@ impl DefCollector<'_> { | |||
204 | ast_id: None, | 204 | ast_id: None, |
205 | krate: Some(krate), | 205 | krate: Some(krate), |
206 | kind: MacroDefKind::CustomDerive(expander), | 206 | kind: MacroDefKind::CustomDerive(expander), |
207 | local_inner: false, | ||
207 | }; | 208 | }; |
208 | 209 | ||
209 | self.define_proc_macro(name.clone(), macro_id); | 210 | self.define_proc_macro(name.clone(), macro_id); |
@@ -301,7 +302,7 @@ impl DefCollector<'_> { | |||
301 | ); | 302 | ); |
302 | 303 | ||
303 | if let Some(ModuleDefId::ModuleId(m)) = res.take_types() { | 304 | if let Some(ModuleDefId::ModuleId(m)) = res.take_types() { |
304 | tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use); | 305 | mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use); |
305 | self.import_all_macros_exported(current_module_id, m.krate); | 306 | self.import_all_macros_exported(current_module_id, m.krate); |
306 | } | 307 | } |
307 | } | 308 | } |
@@ -411,10 +412,10 @@ impl DefCollector<'_> { | |||
411 | match def.take_types() { | 412 | match def.take_types() { |
412 | Some(ModuleDefId::ModuleId(m)) => { | 413 | Some(ModuleDefId::ModuleId(m)) => { |
413 | if import.is_prelude { | 414 | if import.is_prelude { |
414 | tested_by!(std_prelude); | 415 | mark::hit!(std_prelude); |
415 | self.def_map.prelude = Some(m); | 416 | self.def_map.prelude = Some(m); |
416 | } else if m.krate != self.def_map.krate { | 417 | } else if m.krate != self.def_map.krate { |
417 | tested_by!(glob_across_crates); | 418 | mark::hit!(glob_across_crates); |
418 | // glob import from other crate => we can just import everything once | 419 | // glob import from other crate => we can just import everything once |
419 | let item_map = self.db.crate_def_map(m.krate); | 420 | let item_map = self.db.crate_def_map(m.krate); |
420 | let scope = &item_map[m.local_id].scope; | 421 | let scope = &item_map[m.local_id].scope; |
@@ -460,7 +461,7 @@ impl DefCollector<'_> { | |||
460 | } | 461 | } |
461 | } | 462 | } |
462 | Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => { | 463 | Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => { |
463 | tested_by!(glob_enum); | 464 | mark::hit!(glob_enum); |
464 | // glob import from enum => just import all the variants | 465 | // glob import from enum => just import all the variants |
465 | 466 | ||
466 | // XXX: urgh, so this works by accident! Here, we look at | 467 | // XXX: urgh, so this works by accident! Here, we look at |
@@ -509,7 +510,7 @@ impl DefCollector<'_> { | |||
509 | 510 | ||
510 | self.update(module_id, &[(name, def)], vis); | 511 | self.update(module_id, &[(name, def)], vis); |
511 | } | 512 | } |
512 | None => tested_by!(bogus_paths), | 513 | None => mark::hit!(bogus_paths), |
513 | } | 514 | } |
514 | } | 515 | } |
515 | } | 516 | } |
@@ -682,7 +683,7 @@ impl ModCollector<'_, '_> { | |||
682 | // Prelude module is always considered to be `#[macro_use]`. | 683 | // Prelude module is always considered to be `#[macro_use]`. |
683 | if let Some(prelude_module) = self.def_collector.def_map.prelude { | 684 | if let Some(prelude_module) = self.def_collector.def_map.prelude { |
684 | if prelude_module.krate != self.def_collector.def_map.krate { | 685 | if prelude_module.krate != self.def_collector.def_map.krate { |
685 | tested_by!(prelude_is_macro_use); | 686 | mark::hit!(prelude_is_macro_use); |
686 | self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate); | 687 | self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate); |
687 | } | 688 | } |
688 | } | 689 | } |
@@ -829,7 +830,7 @@ impl ModCollector<'_, '_> { | |||
829 | 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 }; |
830 | let def: ModuleDefId = module.into(); | 831 | let def: ModuleDefId = module.into(); |
831 | 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); |
832 | 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); |
833 | res | 834 | res |
834 | } | 835 | } |
835 | 836 | ||
@@ -843,6 +844,8 @@ impl ModCollector<'_, '_> { | |||
843 | let name = def.name.clone(); | 844 | let name = def.name.clone(); |
844 | let container = ContainerId::ModuleId(module); | 845 | let container = ContainerId::ModuleId(module); |
845 | let vis = &def.visibility; | 846 | let vis = &def.visibility; |
847 | let mut has_constructor = false; | ||
848 | |||
846 | let def: ModuleDefId = match def.kind { | 849 | let def: ModuleDefId = match def.kind { |
847 | raw::DefKind::Function(ast_id) => FunctionLoc { | 850 | raw::DefKind::Function(ast_id) => FunctionLoc { |
848 | container: container.into(), | 851 | container: container.into(), |
@@ -850,7 +853,8 @@ impl ModCollector<'_, '_> { | |||
850 | } | 853 | } |
851 | .intern(self.def_collector.db) | 854 | .intern(self.def_collector.db) |
852 | .into(), | 855 | .into(), |
853 | raw::DefKind::Struct(ast_id) => { | 856 | raw::DefKind::Struct(ast_id, mode) => { |
857 | has_constructor = mode != raw::StructDefKind::Record; | ||
854 | StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) } | 858 | StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) } |
855 | .intern(self.def_collector.db) | 859 | .intern(self.def_collector.db) |
856 | .into() | 860 | .into() |
@@ -893,7 +897,11 @@ impl ModCollector<'_, '_> { | |||
893 | .def_map | 897 | .def_map |
894 | .resolve_visibility(self.def_collector.db, self.module_id, vis) | 898 | .resolve_visibility(self.def_collector.db, self.module_id, vis) |
895 | .unwrap_or(Visibility::Public); | 899 | .unwrap_or(Visibility::Public); |
896 | 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 | ) | ||
897 | } | 905 | } |
898 | 906 | ||
899 | fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { | 907 | fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { |
@@ -941,6 +949,7 @@ impl ModCollector<'_, '_> { | |||
941 | ast_id: Some(ast_id.ast_id), | 949 | ast_id: Some(ast_id.ast_id), |
942 | krate: Some(self.def_collector.def_map.krate), | 950 | krate: Some(self.def_collector.def_map.krate), |
943 | kind: MacroDefKind::Declarative, | 951 | kind: MacroDefKind::Declarative, |
952 | local_inner: mac.local_inner, | ||
944 | }; | 953 | }; |
945 | self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export); | 954 | self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export); |
946 | } | 955 | } |
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index 35a0a0c98..19692e70c 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs | |||
@@ -14,7 +14,7 @@ use std::iter::successors; | |||
14 | 14 | ||
15 | use hir_expand::name::Name; | 15 | use hir_expand::name::Name; |
16 | use ra_db::Edition; | 16 | use ra_db::Edition; |
17 | use test_utils::tested_by; | 17 | use test_utils::mark; |
18 | 18 | ||
19 | use crate::{ | 19 | use crate::{ |
20 | db::DefDatabase, | 20 | db::DefDatabase, |
@@ -108,7 +108,7 @@ impl CrateDefMap { | |||
108 | let mut curr_per_ns: PerNs = match path.kind { | 108 | let mut curr_per_ns: PerNs = match path.kind { |
109 | PathKind::DollarCrate(krate) => { | 109 | PathKind::DollarCrate(krate) => { |
110 | if krate == self.krate { | 110 | if krate == self.krate { |
111 | tested_by!(macro_dollar_crate_self); | 111 | mark::hit!(macro_dollar_crate_self); |
112 | PerNs::types( | 112 | PerNs::types( |
113 | ModuleId { krate: self.krate, local_id: self.root }.into(), | 113 | ModuleId { krate: self.krate, local_id: self.root }.into(), |
114 | Visibility::Public, | 114 | Visibility::Public, |
@@ -116,7 +116,7 @@ impl CrateDefMap { | |||
116 | } else { | 116 | } else { |
117 | let def_map = db.crate_def_map(krate); | 117 | let def_map = db.crate_def_map(krate); |
118 | let module = ModuleId { krate, local_id: def_map.root }; | 118 | let module = ModuleId { krate, local_id: def_map.root }; |
119 | tested_by!(macro_dollar_crate_other); | 119 | mark::hit!(macro_dollar_crate_other); |
120 | PerNs::types(module.into(), Visibility::Public) | 120 | PerNs::types(module.into(), Visibility::Public) |
121 | } | 121 | } |
122 | } | 122 | } |
@@ -221,7 +221,7 @@ impl CrateDefMap { | |||
221 | } | 221 | } |
222 | ModuleDefId::AdtId(AdtId::EnumId(e)) => { | 222 | ModuleDefId::AdtId(AdtId::EnumId(e)) => { |
223 | // enum variant | 223 | // enum variant |
224 | tested_by!(can_import_enum_variant); | 224 | mark::hit!(can_import_enum_variant); |
225 | let enum_data = db.enum_data(e); | 225 | let enum_data = db.enum_data(e); |
226 | match enum_data.variant(&segment) { | 226 | match enum_data.variant(&segment) { |
227 | Some(local_id) => { | 227 | Some(local_id) => { |
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index 39b011ad7..f44baa579 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs | |||
@@ -18,7 +18,7 @@ use ra_syntax::{ | |||
18 | ast::{self, AttrsOwner, NameOwner, VisibilityOwner}, | 18 | ast::{self, AttrsOwner, NameOwner, VisibilityOwner}, |
19 | AstNode, | 19 | AstNode, |
20 | }; | 20 | }; |
21 | use test_utils::tested_by; | 21 | use test_utils::mark; |
22 | 22 | ||
23 | use crate::{ | 23 | use crate::{ |
24 | attr::Attrs, | 24 | attr::Attrs, |
@@ -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>), |
@@ -168,10 +175,10 @@ pub(super) enum DefKind { | |||
168 | } | 175 | } |
169 | 176 | ||
170 | impl DefKind { | 177 | 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(), |
@@ -188,6 +195,7 @@ pub(super) struct MacroData { | |||
188 | pub(super) path: ModPath, | 195 | pub(super) path: ModPath, |
189 | pub(super) name: Option<Name>, | 196 | pub(super) name: Option<Name>, |
190 | pub(super) export: bool, | 197 | pub(super) export: bool, |
198 | pub(super) local_inner: bool, | ||
191 | pub(super) builtin: bool, | 199 | pub(super) builtin: bool, |
192 | } | 200 | } |
193 | 201 | ||
@@ -235,9 +243,14 @@ impl RawItemsCollector { | |||
235 | return; | 243 | return; |
236 | } | 244 | } |
237 | 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 | }; | ||
238 | let id = self.source_ast_id_map.ast_id(&it); | 251 | let id = self.source_ast_id_map.ast_id(&it); |
239 | let name = it.name(); | 252 | let name = it.name(); |
240 | (DefKind::Struct(id), name) | 253 | (DefKind::Struct(id, kind), name) |
241 | } | 254 | } |
242 | ast::ModuleItem::UnionDef(it) => { | 255 | ast::ModuleItem::UnionDef(it) => { |
243 | let id = self.source_ast_id_map.ast_id(&it); | 256 | let id = self.source_ast_id_map.ast_id(&it); |
@@ -333,7 +346,7 @@ impl RawItemsCollector { | |||
333 | self.push_item(current_module, attrs, RawItemKind::Module(item)); | 346 | self.push_item(current_module, attrs, RawItemKind::Module(item)); |
334 | return; | 347 | return; |
335 | } | 348 | } |
336 | tested_by!(name_res_works_for_broken_modules); | 349 | mark::hit!(name_res_works_for_broken_modules); |
337 | } | 350 | } |
338 | 351 | ||
339 | fn add_use_item(&mut self, current_module: Option<Idx<ModuleData>>, use_item: ast::UseItem) { | 352 | fn add_use_item(&mut self, current_module: Option<Idx<ModuleData>>, use_item: ast::UseItem) { |
@@ -401,14 +414,32 @@ impl RawItemsCollector { | |||
401 | 414 | ||
402 | let name = m.name().map(|it| it.as_name()); | 415 | let name = m.name().map(|it| it.as_name()); |
403 | let ast_id = self.source_ast_id_map.ast_id(&m); | 416 | let ast_id = self.source_ast_id_map.ast_id(&m); |
404 | // FIXME: cfg_attr | ||
405 | let export = m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "macro_export"); | ||
406 | 417 | ||
407 | // FIXME: cfg_attr | 418 | // FIXME: cfg_attr |
408 | let builtin = | 419 | let export_attr = attrs.by_key("macro_export"); |
409 | m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "rustc_builtin_macro"); | 420 | |
421 | let export = export_attr.exists(); | ||
422 | let local_inner = if export { | ||
423 | export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it { | ||
424 | tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { | ||
425 | ident.text.contains("local_inner_macros") | ||
426 | } | ||
427 | _ => false, | ||
428 | }) | ||
429 | } else { | ||
430 | false | ||
431 | }; | ||
432 | |||
433 | let builtin = attrs.by_key("rustc_builtin_macro").exists(); | ||
410 | 434 | ||
411 | let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export, builtin }); | 435 | let m = self.raw_items.macros.alloc(MacroData { |
436 | ast_id, | ||
437 | path, | ||
438 | name, | ||
439 | export, | ||
440 | local_inner, | ||
441 | builtin, | ||
442 | }); | ||
412 | self.push_item(current_module, attrs, RawItemKind::Macro(m)); | 443 | self.push_item(current_module, attrs, RawItemKind::Macro(m)); |
413 | } | 444 | } |
414 | 445 | ||
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index 83120fa36..05cd0297d 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs | |||
@@ -8,7 +8,7 @@ use std::sync::Arc; | |||
8 | 8 | ||
9 | use insta::assert_snapshot; | 9 | use insta::assert_snapshot; |
10 | use ra_db::{fixture::WithFixture, SourceDatabase}; | 10 | use ra_db::{fixture::WithFixture, SourceDatabase}; |
11 | use test_utils::covers; | 11 | use test_utils::mark; |
12 | 12 | ||
13 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; | 13 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; |
14 | 14 | ||
@@ -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 | } |
@@ -132,7 +132,7 @@ fn crate_def_map_fn_mod_same_name() { | |||
132 | 132 | ||
133 | #[test] | 133 | #[test] |
134 | fn bogus_paths() { | 134 | fn bogus_paths() { |
135 | covers!(bogus_paths); | 135 | mark::check!(bogus_paths); |
136 | let map = def_map( | 136 | let map = def_map( |
137 | " | 137 | " |
138 | //- /lib.rs | 138 | //- /lib.rs |
@@ -247,7 +247,7 @@ fn re_exports() { | |||
247 | 247 | ||
248 | #[test] | 248 | #[test] |
249 | fn std_prelude() { | 249 | fn std_prelude() { |
250 | covers!(std_prelude); | 250 | mark::check!(std_prelude); |
251 | let map = def_map( | 251 | let map = def_map( |
252 | " | 252 | " |
253 | //- /main.rs crate:main deps:test_crate | 253 | //- /main.rs crate:main deps:test_crate |
@@ -271,7 +271,7 @@ fn std_prelude() { | |||
271 | 271 | ||
272 | #[test] | 272 | #[test] |
273 | fn can_import_enum_variant() { | 273 | fn can_import_enum_variant() { |
274 | covers!(can_import_enum_variant); | 274 | mark::check!(can_import_enum_variant); |
275 | let map = def_map( | 275 | let map = def_map( |
276 | " | 276 | " |
277 | //- /lib.rs | 277 | //- /lib.rs |
diff --git a/crates/ra_hir_def/src/nameres/tests/globs.rs b/crates/ra_hir_def/src/nameres/tests/globs.rs index ee8df3a26..2b12c0daa 100644 --- a/crates/ra_hir_def/src/nameres/tests/globs.rs +++ b/crates/ra_hir_def/src/nameres/tests/globs.rs | |||
@@ -152,7 +152,7 @@ fn glob_privacy_2() { | |||
152 | 152 | ||
153 | #[test] | 153 | #[test] |
154 | fn glob_across_crates() { | 154 | fn glob_across_crates() { |
155 | covers!(glob_across_crates); | 155 | mark::check!(glob_across_crates); |
156 | let map = def_map( | 156 | let map = def_map( |
157 | r" | 157 | r" |
158 | //- /main.rs crate:main deps:test_crate | 158 | //- /main.rs crate:main deps:test_crate |
@@ -171,7 +171,6 @@ fn glob_across_crates() { | |||
171 | 171 | ||
172 | #[test] | 172 | #[test] |
173 | fn glob_privacy_across_crates() { | 173 | fn glob_privacy_across_crates() { |
174 | covers!(glob_across_crates); | ||
175 | let map = def_map( | 174 | let map = def_map( |
176 | r" | 175 | r" |
177 | //- /main.rs crate:main deps:test_crate | 176 | //- /main.rs crate:main deps:test_crate |
@@ -191,7 +190,7 @@ fn glob_privacy_across_crates() { | |||
191 | 190 | ||
192 | #[test] | 191 | #[test] |
193 | fn glob_enum() { | 192 | fn glob_enum() { |
194 | covers!(glob_enum); | 193 | mark::check!(glob_enum); |
195 | let map = def_map( | 194 | let map = def_map( |
196 | " | 195 | " |
197 | //- /lib.rs | 196 | //- /lib.rs |
@@ -212,7 +211,7 @@ fn glob_enum() { | |||
212 | 211 | ||
213 | #[test] | 212 | #[test] |
214 | fn glob_enum_group() { | 213 | fn glob_enum_group() { |
215 | covers!(glob_enum_group); | 214 | mark::check!(glob_enum_group); |
216 | let map = def_map( | 215 | let map = def_map( |
217 | r" | 216 | r" |
218 | //- /lib.rs | 217 | //- /lib.rs |
diff --git a/crates/ra_hir_def/src/nameres/tests/macros.rs b/crates/ra_hir_def/src/nameres/tests/macros.rs index b0befdfbd..84480d9f6 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,50 @@ 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 | ||
135 | "###); | ||
136 | } | ||
137 | |||
138 | #[test] | ||
139 | fn local_inner_macros_makes_local_macros_usable() { | ||
140 | let map = def_map( | ||
141 | " | ||
142 | //- /main.rs crate:main deps:foo | ||
143 | foo::structs!(Foo, Bar); | ||
144 | mod bar; | ||
145 | //- /bar.rs | ||
146 | use crate::*; | ||
147 | //- /lib.rs crate:foo | ||
148 | #[macro_export(local_inner_macros)] | ||
149 | macro_rules! structs { | ||
150 | ($($i:ident),*) => { | ||
151 | inner!($($i),*); | ||
152 | } | ||
153 | } | ||
154 | #[macro_export] | ||
155 | macro_rules! inner { | ||
156 | ($($i:ident),*) => { | ||
157 | $(struct $i { field: u32 } )* | ||
158 | } | ||
159 | } | ||
160 | ", | ||
161 | ); | ||
162 | assert_snapshot!(map, @r###" | ||
163 | â‹®crate | ||
164 | â‹®Bar: t | ||
165 | â‹®Foo: t | ||
166 | â‹®bar: t | ||
167 | â‹® | ||
168 | â‹®crate::bar | ||
169 | â‹®Bar: t | ||
170 | â‹®Foo: t | ||
134 | â‹®bar: t | 171 | â‹®bar: t |
135 | "###); | 172 | "###); |
136 | } | 173 | } |
@@ -167,7 +204,7 @@ fn unexpanded_macro_should_expand_by_fixedpoint_loop() { | |||
167 | ); | 204 | ); |
168 | assert_snapshot!(map, @r###" | 205 | assert_snapshot!(map, @r###" |
169 | â‹®crate | 206 | â‹®crate |
170 | â‹®Foo: t v | 207 | â‹®Foo: t |
171 | â‹®bar: m | 208 | â‹®bar: m |
172 | â‹®foo: m | 209 | â‹®foo: m |
173 | "###); | 210 | "###); |
@@ -175,7 +212,7 @@ fn unexpanded_macro_should_expand_by_fixedpoint_loop() { | |||
175 | 212 | ||
176 | #[test] | 213 | #[test] |
177 | fn macro_rules_from_other_crates_are_visible_with_macro_use() { | 214 | fn macro_rules_from_other_crates_are_visible_with_macro_use() { |
178 | covers!(macro_rules_from_other_crates_are_visible_with_macro_use); | 215 | mark::check!(macro_rules_from_other_crates_are_visible_with_macro_use); |
179 | let map = def_map( | 216 | let map = def_map( |
180 | " | 217 | " |
181 | //- /main.rs crate:main deps:foo | 218 | //- /main.rs crate:main deps:foo |
@@ -225,7 +262,7 @@ fn macro_rules_from_other_crates_are_visible_with_macro_use() { | |||
225 | 262 | ||
226 | #[test] | 263 | #[test] |
227 | fn prelude_is_macro_use() { | 264 | fn prelude_is_macro_use() { |
228 | covers!(prelude_is_macro_use); | 265 | mark::check!(prelude_is_macro_use); |
229 | let map = def_map( | 266 | let map = def_map( |
230 | " | 267 | " |
231 | //- /main.rs crate:main deps:foo | 268 | //- /main.rs crate:main deps:foo |
@@ -507,8 +544,7 @@ fn path_qualified_macros() { | |||
507 | 544 | ||
508 | #[test] | 545 | #[test] |
509 | fn macro_dollar_crate_is_correct_in_item() { | 546 | fn macro_dollar_crate_is_correct_in_item() { |
510 | covers!(macro_dollar_crate_self); | 547 | mark::check!(macro_dollar_crate_self); |
511 | covers!(macro_dollar_crate_other); | ||
512 | let map = def_map( | 548 | let map = def_map( |
513 | " | 549 | " |
514 | //- /main.rs crate:main deps:foo | 550 | //- /main.rs crate:main deps:foo |
@@ -566,7 +602,7 @@ fn macro_dollar_crate_is_correct_in_item() { | |||
566 | 602 | ||
567 | #[test] | 603 | #[test] |
568 | fn macro_dollar_crate_is_correct_in_indirect_deps() { | 604 | fn macro_dollar_crate_is_correct_in_indirect_deps() { |
569 | covers!(macro_dollar_crate_other); | 605 | mark::check!(macro_dollar_crate_other); |
570 | // From std | 606 | // From std |
571 | let map = def_map( | 607 | let map = def_map( |
572 | r#" | 608 | r#" |
diff --git a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs index 37fcdfb8c..b43b294ca 100644 --- a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs +++ b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs | |||
@@ -2,7 +2,7 @@ use super::*; | |||
2 | 2 | ||
3 | #[test] | 3 | #[test] |
4 | fn name_res_works_for_broken_modules() { | 4 | fn name_res_works_for_broken_modules() { |
5 | covers!(name_res_works_for_broken_modules); | 5 | mark::check!(name_res_works_for_broken_modules); |
6 | let map = def_map( | 6 | let map = def_map( |
7 | r" | 7 | r" |
8 | //- /lib.rs | 8 | //- /lib.rs |
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 162b3c8c7..e84efe2ab 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs | |||
@@ -7,6 +7,7 @@ use std::{ | |||
7 | sync::Arc, | 7 | sync::Arc, |
8 | }; | 8 | }; |
9 | 9 | ||
10 | use crate::body::LowerCtx; | ||
10 | use hir_expand::{ | 11 | use hir_expand::{ |
11 | hygiene::Hygiene, | 12 | hygiene::Hygiene, |
12 | name::{AsName, Name}, | 13 | name::{AsName, Name}, |
@@ -244,8 +245,8 @@ impl<'a> PathSegments<'a> { | |||
244 | } | 245 | } |
245 | 246 | ||
246 | impl GenericArgs { | 247 | impl GenericArgs { |
247 | pub(crate) fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> { | 248 | pub(crate) fn from_ast(lower_ctx: &LowerCtx, node: ast::TypeArgList) -> Option<GenericArgs> { |
248 | lower::lower_generic_args(node) | 249 | lower::lower_generic_args(lower_ctx, node) |
249 | } | 250 | } |
250 | 251 | ||
251 | pub(crate) fn empty() -> GenericArgs { | 252 | pub(crate) fn empty() -> GenericArgs { |
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs index 9ec2e0dcd..6a0c019fd 100644 --- a/crates/ra_hir_def/src/path/lower.rs +++ b/crates/ra_hir_def/src/path/lower.rs | |||
@@ -13,6 +13,7 @@ use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner, TypeBoundsOwner}; | |||
13 | 13 | ||
14 | use super::AssociatedTypeBinding; | 14 | use super::AssociatedTypeBinding; |
15 | use crate::{ | 15 | use crate::{ |
16 | body::LowerCtx, | ||
16 | path::{GenericArg, GenericArgs, ModPath, Path, PathKind}, | 17 | path::{GenericArg, GenericArgs, ModPath, Path, PathKind}, |
17 | type_ref::{TypeBound, TypeRef}, | 18 | type_ref::{TypeBound, TypeRef}, |
18 | }; | 19 | }; |
@@ -26,6 +27,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
26 | let mut type_anchor = None; | 27 | let mut type_anchor = None; |
27 | let mut segments = Vec::new(); | 28 | let mut segments = Vec::new(); |
28 | let mut generic_args = Vec::new(); | 29 | let mut generic_args = Vec::new(); |
30 | let ctx = LowerCtx::with_hygiene(hygiene); | ||
29 | loop { | 31 | loop { |
30 | let segment = path.segment()?; | 32 | let segment = path.segment()?; |
31 | 33 | ||
@@ -40,9 +42,10 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
40 | Either::Left(name) => { | 42 | Either::Left(name) => { |
41 | let args = segment | 43 | let args = segment |
42 | .type_arg_list() | 44 | .type_arg_list() |
43 | .and_then(lower_generic_args) | 45 | .and_then(|it| lower_generic_args(&ctx, it)) |
44 | .or_else(|| { | 46 | .or_else(|| { |
45 | lower_generic_args_from_fn_path( | 47 | lower_generic_args_from_fn_path( |
48 | &ctx, | ||
46 | segment.param_list(), | 49 | segment.param_list(), |
47 | segment.ret_type(), | 50 | segment.ret_type(), |
48 | ) | 51 | ) |
@@ -60,7 +63,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
60 | ast::PathSegmentKind::Type { type_ref, trait_ref } => { | 63 | ast::PathSegmentKind::Type { type_ref, trait_ref } => { |
61 | assert!(path.qualifier().is_none()); // this can only occur at the first segment | 64 | assert!(path.qualifier().is_none()); // this can only occur at the first segment |
62 | 65 | ||
63 | let self_type = TypeRef::from_ast(type_ref?); | 66 | let self_type = TypeRef::from_ast(&ctx, type_ref?); |
64 | 67 | ||
65 | match trait_ref { | 68 | match trait_ref { |
66 | // <T>::foo | 69 | // <T>::foo |
@@ -113,6 +116,21 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
113 | } | 116 | } |
114 | segments.reverse(); | 117 | segments.reverse(); |
115 | generic_args.reverse(); | 118 | generic_args.reverse(); |
119 | |||
120 | // handle local_inner_macros : | ||
121 | // Basically, even in rustc it is quite hacky: | ||
122 | // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456 | ||
123 | // We follow what it did anyway :) | ||
124 | if segments.len() == 1 && kind == PathKind::Plain { | ||
125 | if let Some(macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) { | ||
126 | if macro_call.is_bang() { | ||
127 | if let Some(crate_id) = hygiene.local_inner_macros() { | ||
128 | kind = PathKind::DollarCrate(crate_id); | ||
129 | } | ||
130 | } | ||
131 | } | ||
132 | } | ||
133 | |||
116 | let mod_path = ModPath { kind, segments }; | 134 | let mod_path = ModPath { kind, segments }; |
117 | return Some(Path { type_anchor, mod_path, generic_args }); | 135 | return Some(Path { type_anchor, mod_path, generic_args }); |
118 | 136 | ||
@@ -128,10 +146,13 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
128 | } | 146 | } |
129 | } | 147 | } |
130 | 148 | ||
131 | pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs> { | 149 | pub(super) fn lower_generic_args( |
150 | lower_ctx: &LowerCtx, | ||
151 | node: ast::TypeArgList, | ||
152 | ) -> Option<GenericArgs> { | ||
132 | let mut args = Vec::new(); | 153 | let mut args = Vec::new(); |
133 | for type_arg in node.type_args() { | 154 | for type_arg in node.type_args() { |
134 | let type_ref = TypeRef::from_ast_opt(type_arg.type_ref()); | 155 | let type_ref = TypeRef::from_ast_opt(lower_ctx, type_arg.type_ref()); |
135 | args.push(GenericArg::Type(type_ref)); | 156 | args.push(GenericArg::Type(type_ref)); |
136 | } | 157 | } |
137 | // lifetimes ignored for now | 158 | // lifetimes ignored for now |
@@ -140,9 +161,9 @@ pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs> | |||
140 | let assoc_type_arg: ast::AssocTypeArg = assoc_type_arg; | 161 | let assoc_type_arg: ast::AssocTypeArg = assoc_type_arg; |
141 | if let Some(name_ref) = assoc_type_arg.name_ref() { | 162 | if let Some(name_ref) = assoc_type_arg.name_ref() { |
142 | let name = name_ref.as_name(); | 163 | let name = name_ref.as_name(); |
143 | let type_ref = assoc_type_arg.type_ref().map(TypeRef::from_ast); | 164 | let type_ref = assoc_type_arg.type_ref().map(|it| TypeRef::from_ast(lower_ctx, it)); |
144 | let bounds = if let Some(l) = assoc_type_arg.type_bound_list() { | 165 | let bounds = if let Some(l) = assoc_type_arg.type_bound_list() { |
145 | l.bounds().map(TypeBound::from_ast).collect() | 166 | l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect() |
146 | } else { | 167 | } else { |
147 | Vec::new() | 168 | Vec::new() |
148 | }; | 169 | }; |
@@ -159,6 +180,7 @@ pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs> | |||
159 | /// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y) | 180 | /// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y) |
160 | /// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`). | 181 | /// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`). |
161 | fn lower_generic_args_from_fn_path( | 182 | fn lower_generic_args_from_fn_path( |
183 | ctx: &LowerCtx, | ||
162 | params: Option<ast::ParamList>, | 184 | params: Option<ast::ParamList>, |
163 | ret_type: Option<ast::RetType>, | 185 | ret_type: Option<ast::RetType>, |
164 | ) -> Option<GenericArgs> { | 186 | ) -> Option<GenericArgs> { |
@@ -167,14 +189,14 @@ fn lower_generic_args_from_fn_path( | |||
167 | if let Some(params) = params { | 189 | if let Some(params) = params { |
168 | let mut param_types = Vec::new(); | 190 | let mut param_types = Vec::new(); |
169 | for param in params.params() { | 191 | for param in params.params() { |
170 | let type_ref = TypeRef::from_ast_opt(param.ascribed_type()); | 192 | let type_ref = TypeRef::from_ast_opt(&ctx, param.ascribed_type()); |
171 | param_types.push(type_ref); | 193 | param_types.push(type_ref); |
172 | } | 194 | } |
173 | let arg = GenericArg::Type(TypeRef::Tuple(param_types)); | 195 | let arg = GenericArg::Type(TypeRef::Tuple(param_types)); |
174 | args.push(arg); | 196 | args.push(arg); |
175 | } | 197 | } |
176 | if let Some(ret_type) = ret_type { | 198 | if let Some(ret_type) = ret_type { |
177 | let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); | 199 | let type_ref = TypeRef::from_ast_opt(&ctx, ret_type.type_ref()); |
178 | bindings.push(AssociatedTypeBinding { | 200 | bindings.push(AssociatedTypeBinding { |
179 | name: name![Output], | 201 | name: name![Output], |
180 | type_ref: Some(type_ref), | 202 | type_ref: Some(type_ref), |
diff --git a/crates/ra_hir_def/src/path/lower/lower_use.rs b/crates/ra_hir_def/src/path/lower/lower_use.rs index 5b6854b0f..7cc655487 100644 --- a/crates/ra_hir_def/src/path/lower/lower_use.rs +++ b/crates/ra_hir_def/src/path/lower/lower_use.rs | |||
@@ -6,7 +6,7 @@ use std::iter; | |||
6 | use either::Either; | 6 | use either::Either; |
7 | use hir_expand::{hygiene::Hygiene, name::AsName}; | 7 | use hir_expand::{hygiene::Hygiene, name::AsName}; |
8 | use ra_syntax::ast::{self, NameOwner}; | 8 | use ra_syntax::ast::{self, NameOwner}; |
9 | use test_utils::tested_by; | 9 | use test_utils::mark; |
10 | 10 | ||
11 | use crate::path::{ImportAlias, ModPath, PathKind}; | 11 | use crate::path::{ImportAlias, ModPath, PathKind}; |
12 | 12 | ||
@@ -54,7 +54,7 @@ pub(crate) fn lower_use_tree( | |||
54 | // FIXME: report errors somewhere | 54 | // FIXME: report errors somewhere |
55 | // We get here if we do | 55 | // We get here if we do |
56 | } else if is_glob { | 56 | } else if is_glob { |
57 | tested_by!(glob_enum_group); | 57 | mark::hit!(glob_enum_group); |
58 | if let Some(prefix) = prefix { | 58 | if let Some(prefix) = prefix { |
59 | cb(prefix, &tree, is_glob, None) | 59 | cb(prefix, &tree, is_glob, None) |
60 | } | 60 | } |
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index 717506358..15fdd9019 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs | |||
@@ -86,6 +86,7 @@ pub enum ResolveValueResult { | |||
86 | 86 | ||
87 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 87 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
88 | pub enum ValueNs { | 88 | pub enum ValueNs { |
89 | ImplSelf(ImplId), | ||
89 | LocalBinding(PatId), | 90 | LocalBinding(PatId), |
90 | FunctionId(FunctionId), | 91 | FunctionId(FunctionId), |
91 | ConstId(ConstId), | 92 | ConstId(ConstId), |
@@ -291,19 +292,26 @@ impl Resolver { | |||
291 | } | 292 | } |
292 | Scope::GenericParams { .. } => continue, | 293 | Scope::GenericParams { .. } => continue, |
293 | 294 | ||
294 | Scope::ImplDefScope(impl_) if n_segments > 1 => { | 295 | Scope::ImplDefScope(impl_) => { |
295 | if first_name == &name![Self] { | 296 | if first_name == &name![Self] { |
296 | let ty = TypeNs::SelfType(*impl_); | 297 | if n_segments > 1 { |
297 | return Some(ResolveValueResult::Partial(ty, 1)); | 298 | let ty = TypeNs::SelfType(*impl_); |
299 | return Some(ResolveValueResult::Partial(ty, 1)); | ||
300 | } else { | ||
301 | return Some(ResolveValueResult::ValueNs(ValueNs::ImplSelf(*impl_))); | ||
302 | } | ||
298 | } | 303 | } |
299 | } | 304 | } |
300 | Scope::AdtScope(adt) if n_segments > 1 => { | 305 | Scope::AdtScope(adt) => { |
306 | if n_segments == 1 { | ||
307 | // bare `Self` doesn't work in the value namespace in a struct/enum definition | ||
308 | continue; | ||
309 | } | ||
301 | if first_name == &name![Self] { | 310 | if first_name == &name![Self] { |
302 | let ty = TypeNs::AdtSelfType(*adt); | 311 | let ty = TypeNs::AdtSelfType(*adt); |
303 | return Some(ResolveValueResult::Partial(ty, 1)); | 312 | return Some(ResolveValueResult::Partial(ty, 1)); |
304 | } | 313 | } |
305 | } | 314 | } |
306 | Scope::ImplDefScope(_) | Scope::AdtScope(_) => continue, | ||
307 | 315 | ||
308 | Scope::ModuleScope(m) => { | 316 | Scope::ModuleScope(m) => { |
309 | let (module_def, idx) = m.crate_def_map.resolve_path( | 317 | let (module_def, idx) = m.crate_def_map.resolve_path( |
diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs index f308c6bdf..86a77b704 100644 --- a/crates/ra_hir_def/src/type_ref.rs +++ b/crates/ra_hir_def/src/type_ref.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | use ra_syntax::ast::{self, TypeAscriptionOwner, TypeBoundsOwner}; | 4 | use ra_syntax::ast::{self, TypeAscriptionOwner, TypeBoundsOwner}; |
5 | 5 | ||
6 | use crate::path::Path; | 6 | use crate::{body::LowerCtx, path::Path}; |
7 | 7 | ||
8 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | 8 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] |
9 | pub enum Mutability { | 9 | pub enum Mutability { |
@@ -35,6 +35,22 @@ impl Mutability { | |||
35 | } | 35 | } |
36 | } | 36 | } |
37 | 37 | ||
38 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | ||
39 | pub enum Rawness { | ||
40 | RawPtr, | ||
41 | Ref, | ||
42 | } | ||
43 | |||
44 | impl Rawness { | ||
45 | pub fn from_raw(is_raw: bool) -> Rawness { | ||
46 | if is_raw { | ||
47 | Rawness::RawPtr | ||
48 | } else { | ||
49 | Rawness::Ref | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | |||
38 | /// Compare ty::Ty | 54 | /// Compare ty::Ty |
39 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | 55 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
40 | pub enum TypeRef { | 56 | pub enum TypeRef { |
@@ -64,30 +80,34 @@ pub enum TypeBound { | |||
64 | 80 | ||
65 | impl TypeRef { | 81 | impl TypeRef { |
66 | /// Converts an `ast::TypeRef` to a `hir::TypeRef`. | 82 | /// Converts an `ast::TypeRef` to a `hir::TypeRef`. |
67 | pub(crate) fn from_ast(node: ast::TypeRef) -> Self { | 83 | pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::TypeRef) -> Self { |
68 | match node { | 84 | match node { |
69 | ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(inner.type_ref()), | 85 | ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(&ctx, inner.type_ref()), |
70 | ast::TypeRef::TupleType(inner) => { | 86 | ast::TypeRef::TupleType(inner) => { |
71 | TypeRef::Tuple(inner.fields().map(TypeRef::from_ast).collect()) | 87 | TypeRef::Tuple(inner.fields().map(|it| TypeRef::from_ast(ctx, it)).collect()) |
72 | } | 88 | } |
73 | ast::TypeRef::NeverType(..) => TypeRef::Never, | 89 | ast::TypeRef::NeverType(..) => TypeRef::Never, |
74 | ast::TypeRef::PathType(inner) => { | 90 | ast::TypeRef::PathType(inner) => { |
75 | // FIXME: Use `Path::from_src` | 91 | // FIXME: Use `Path::from_src` |
76 | inner.path().and_then(Path::from_ast).map(TypeRef::Path).unwrap_or(TypeRef::Error) | 92 | inner |
93 | .path() | ||
94 | .and_then(|it| ctx.lower_path(it)) | ||
95 | .map(TypeRef::Path) | ||
96 | .unwrap_or(TypeRef::Error) | ||
77 | } | 97 | } |
78 | ast::TypeRef::PointerType(inner) => { | 98 | ast::TypeRef::PointerType(inner) => { |
79 | let inner_ty = TypeRef::from_ast_opt(inner.type_ref()); | 99 | let inner_ty = TypeRef::from_ast_opt(&ctx, inner.type_ref()); |
80 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); | 100 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); |
81 | TypeRef::RawPtr(Box::new(inner_ty), mutability) | 101 | TypeRef::RawPtr(Box::new(inner_ty), mutability) |
82 | } | 102 | } |
83 | ast::TypeRef::ArrayType(inner) => { | 103 | ast::TypeRef::ArrayType(inner) => { |
84 | TypeRef::Array(Box::new(TypeRef::from_ast_opt(inner.type_ref()))) | 104 | TypeRef::Array(Box::new(TypeRef::from_ast_opt(&ctx, inner.type_ref()))) |
85 | } | 105 | } |
86 | ast::TypeRef::SliceType(inner) => { | 106 | ast::TypeRef::SliceType(inner) => { |
87 | TypeRef::Slice(Box::new(TypeRef::from_ast_opt(inner.type_ref()))) | 107 | TypeRef::Slice(Box::new(TypeRef::from_ast_opt(&ctx, inner.type_ref()))) |
88 | } | 108 | } |
89 | ast::TypeRef::ReferenceType(inner) => { | 109 | ast::TypeRef::ReferenceType(inner) => { |
90 | let inner_ty = TypeRef::from_ast_opt(inner.type_ref()); | 110 | let inner_ty = TypeRef::from_ast_opt(&ctx, inner.type_ref()); |
91 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); | 111 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); |
92 | TypeRef::Reference(Box::new(inner_ty), mutability) | 112 | TypeRef::Reference(Box::new(inner_ty), mutability) |
93 | } | 113 | } |
@@ -96,10 +116,13 @@ impl TypeRef { | |||
96 | let ret_ty = inner | 116 | let ret_ty = inner |
97 | .ret_type() | 117 | .ret_type() |
98 | .and_then(|rt| rt.type_ref()) | 118 | .and_then(|rt| rt.type_ref()) |
99 | .map(TypeRef::from_ast) | 119 | .map(|it| TypeRef::from_ast(ctx, it)) |
100 | .unwrap_or_else(|| TypeRef::Tuple(Vec::new())); | 120 | .unwrap_or_else(|| TypeRef::Tuple(Vec::new())); |
101 | let mut params = if let Some(pl) = inner.param_list() { | 121 | let mut params = if let Some(pl) = inner.param_list() { |
102 | pl.params().map(|p| p.ascribed_type()).map(TypeRef::from_ast_opt).collect() | 122 | pl.params() |
123 | .map(|p| p.ascribed_type()) | ||
124 | .map(|it| TypeRef::from_ast_opt(&ctx, it)) | ||
125 | .collect() | ||
103 | } else { | 126 | } else { |
104 | Vec::new() | 127 | Vec::new() |
105 | }; | 128 | }; |
@@ -107,19 +130,19 @@ impl TypeRef { | |||
107 | TypeRef::Fn(params) | 130 | TypeRef::Fn(params) |
108 | } | 131 | } |
109 | // for types are close enough for our purposes to the inner type for now... | 132 | // for types are close enough for our purposes to the inner type for now... |
110 | ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(inner.type_ref()), | 133 | ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(&ctx, inner.type_ref()), |
111 | ast::TypeRef::ImplTraitType(inner) => { | 134 | ast::TypeRef::ImplTraitType(inner) => { |
112 | TypeRef::ImplTrait(type_bounds_from_ast(inner.type_bound_list())) | 135 | TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list())) |
113 | } | 136 | } |
114 | ast::TypeRef::DynTraitType(inner) => { | 137 | ast::TypeRef::DynTraitType(inner) => { |
115 | TypeRef::DynTrait(type_bounds_from_ast(inner.type_bound_list())) | 138 | TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list())) |
116 | } | 139 | } |
117 | } | 140 | } |
118 | } | 141 | } |
119 | 142 | ||
120 | pub(crate) fn from_ast_opt(node: Option<ast::TypeRef>) -> Self { | 143 | pub(crate) fn from_ast_opt(ctx: &LowerCtx, node: Option<ast::TypeRef>) -> Self { |
121 | if let Some(node) = node { | 144 | if let Some(node) = node { |
122 | TypeRef::from_ast(node) | 145 | TypeRef::from_ast(ctx, node) |
123 | } else { | 146 | } else { |
124 | TypeRef::Error | 147 | TypeRef::Error |
125 | } | 148 | } |
@@ -180,24 +203,27 @@ impl TypeRef { | |||
180 | } | 203 | } |
181 | } | 204 | } |
182 | 205 | ||
183 | pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) -> Vec<TypeBound> { | 206 | pub(crate) fn type_bounds_from_ast( |
207 | lower_ctx: &LowerCtx, | ||
208 | type_bounds_opt: Option<ast::TypeBoundList>, | ||
209 | ) -> Vec<TypeBound> { | ||
184 | if let Some(type_bounds) = type_bounds_opt { | 210 | if let Some(type_bounds) = type_bounds_opt { |
185 | type_bounds.bounds().map(TypeBound::from_ast).collect() | 211 | type_bounds.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect() |
186 | } else { | 212 | } else { |
187 | vec![] | 213 | vec![] |
188 | } | 214 | } |
189 | } | 215 | } |
190 | 216 | ||
191 | impl TypeBound { | 217 | impl TypeBound { |
192 | pub(crate) fn from_ast(node: ast::TypeBound) -> Self { | 218 | pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::TypeBound) -> Self { |
193 | match node.kind() { | 219 | match node.kind() { |
194 | ast::TypeBoundKind::PathType(path_type) => { | 220 | ast::TypeBoundKind::PathType(path_type) => { |
195 | let path = match path_type.path() { | 221 | let path = match path_type.path() { |
196 | Some(p) => p, | 222 | Some(p) => p, |
197 | None => return TypeBound::Error, | 223 | None => return TypeBound::Error, |
198 | }; | 224 | }; |
199 | // FIXME: Use `Path::from_src` | 225 | |
200 | let path = match Path::from_ast(path) { | 226 | let path = match ctx.lower_path(path) { |
201 | Some(p) => p, | 227 | Some(p) => p, |
202 | None => return TypeBound::Error, | 228 | None => return TypeBound::Error, |
203 | }; | 229 | }; |