diff options
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r-- | crates/hir_def/src/body.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 17 | ||||
-rw-r--r-- | crates/hir_def/src/body/tests/block.rs | 29 | ||||
-rw-r--r-- | crates/hir_def/src/builtin_type.rs | 132 | ||||
-rw-r--r-- | crates/hir_def/src/diagnostics.rs | 28 | ||||
-rw-r--r-- | crates/hir_def/src/expr.rs | 3 | ||||
-rw-r--r-- | crates/hir_def/src/find_path.rs | 59 | ||||
-rw-r--r-- | crates/hir_def/src/item_scope.rs | 22 | ||||
-rw-r--r-- | crates/hir_def/src/lib.rs | 137 | ||||
-rw-r--r-- | crates/hir_def/src/nameres.rs | 26 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 81 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/path_resolution.rs | 21 | ||||
-rw-r--r-- | crates/hir_def/src/path/lower.rs | 13 |
13 files changed, 365 insertions, 205 deletions
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index 9a432f7d1..ff4b4a0cf 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -123,7 +123,7 @@ impl Expander { | |||
123 | Some(it) => it, | 123 | Some(it) => it, |
124 | None => { | 124 | None => { |
125 | if err.is_none() { | 125 | if err.is_none() { |
126 | eprintln!("no error despite `as_call_id_with_errors` returning `None`"); | 126 | log::warn!("no error despite `as_call_id_with_errors` returning `None`"); |
127 | } | 127 | } |
128 | return ExpandResult { value: None, err }; | 128 | return ExpandResult { value: None, err }; |
129 | } | 129 | } |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index c18001e15..40beb2f7a 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -24,7 +24,7 @@ use test_utils::mark; | |||
24 | use crate::{ | 24 | use crate::{ |
25 | adt::StructKind, | 25 | adt::StructKind, |
26 | body::{Body, BodySourceMap, Expander, LabelSource, PatPtr, SyntheticSyntax}, | 26 | body::{Body, BodySourceMap, Expander, LabelSource, PatPtr, SyntheticSyntax}, |
27 | builtin_type::{BuiltinFloat, BuiltinInt}, | 27 | builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}, |
28 | db::DefDatabase, | 28 | db::DefDatabase, |
29 | diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro}, | 29 | diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro}, |
30 | expr::{ | 30 | expr::{ |
@@ -1065,11 +1065,16 @@ impl From<ast::LiteralKind> for Literal { | |||
1065 | fn from(ast_lit_kind: ast::LiteralKind) -> Self { | 1065 | fn from(ast_lit_kind: ast::LiteralKind) -> Self { |
1066 | match ast_lit_kind { | 1066 | match ast_lit_kind { |
1067 | LiteralKind::IntNumber(lit) => { | 1067 | LiteralKind::IntNumber(lit) => { |
1068 | if let Some(float_suffix) = lit.suffix().and_then(BuiltinFloat::from_suffix) { | 1068 | if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) { |
1069 | return Literal::Float(Default::default(), Some(float_suffix)); | 1069 | return Literal::Float(Default::default(), builtin); |
1070 | } else if let builtin @ Some(_) = | ||
1071 | lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it)) | ||
1072 | { | ||
1073 | Literal::Int(Default::default(), builtin) | ||
1074 | } else { | ||
1075 | let builtin = lit.suffix().and_then(|it| BuiltinUint::from_suffix(&it)); | ||
1076 | Literal::Uint(Default::default(), builtin) | ||
1070 | } | 1077 | } |
1071 | let ty = lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it)); | ||
1072 | Literal::Int(Default::default(), ty) | ||
1073 | } | 1078 | } |
1074 | LiteralKind::FloatNumber(lit) => { | 1079 | LiteralKind::FloatNumber(lit) => { |
1075 | let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it)); | 1080 | let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it)); |
@@ -1077,7 +1082,7 @@ impl From<ast::LiteralKind> for Literal { | |||
1077 | } | 1082 | } |
1078 | LiteralKind::ByteString(_) => Literal::ByteString(Default::default()), | 1083 | LiteralKind::ByteString(_) => Literal::ByteString(Default::default()), |
1079 | LiteralKind::String(_) => Literal::String(Default::default()), | 1084 | LiteralKind::String(_) => Literal::String(Default::default()), |
1080 | LiteralKind::Byte => Literal::Int(Default::default(), Some(BuiltinInt::U8)), | 1085 | LiteralKind::Byte => Literal::Uint(Default::default(), Some(BuiltinUint::U8)), |
1081 | LiteralKind::Bool(val) => Literal::Bool(val), | 1086 | LiteralKind::Bool(val) => Literal::Bool(val), |
1082 | LiteralKind::Char => Literal::Char(Default::default()), | 1087 | LiteralKind::Char => Literal::Char(Default::default()), |
1083 | } | 1088 | } |
diff --git a/crates/hir_def/src/body/tests/block.rs b/crates/hir_def/src/body/tests/block.rs index a5ec0883f..8bca72a17 100644 --- a/crates/hir_def/src/body/tests/block.rs +++ b/crates/hir_def/src/body/tests/block.rs | |||
@@ -259,3 +259,32 @@ fn main() { | |||
259 | "#]], | 259 | "#]], |
260 | ); | 260 | ); |
261 | } | 261 | } |
262 | |||
263 | #[test] | ||
264 | fn underscore_import() { | ||
265 | // This used to panic, because the default (private) visibility inside block expressions would | ||
266 | // point into the containing `DefMap`, which visibilities should never be able to do. | ||
267 | mark::check!(adjust_vis_in_block_def_map); | ||
268 | check_at( | ||
269 | r#" | ||
270 | mod m { | ||
271 | fn main() { | ||
272 | use Tr as _; | ||
273 | trait Tr {} | ||
274 | $0 | ||
275 | } | ||
276 | } | ||
277 | "#, | ||
278 | expect![[r#" | ||
279 | block scope | ||
280 | _: t | ||
281 | Tr: t | ||
282 | |||
283 | crate | ||
284 | m: t | ||
285 | |||
286 | crate::m | ||
287 | main: v | ||
288 | "#]], | ||
289 | ); | ||
290 | } | ||
diff --git a/crates/hir_def/src/builtin_type.rs b/crates/hir_def/src/builtin_type.rs index 0f872b5c0..7cbaf30b8 100644 --- a/crates/hir_def/src/builtin_type.rs +++ b/crates/hir_def/src/builtin_type.rs | |||
@@ -6,38 +6,32 @@ | |||
6 | use std::fmt; | 6 | use std::fmt; |
7 | 7 | ||
8 | use hir_expand::name::{name, AsName, Name}; | 8 | use hir_expand::name::{name, AsName, Name}; |
9 | 9 | /// Different signed int types. | |
10 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] | 10 | #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
11 | pub enum Signedness { | 11 | pub enum BuiltinInt { |
12 | Signed, | 12 | Isize, |
13 | Unsigned, | 13 | I8, |
14 | } | 14 | I16, |
15 | 15 | I32, | |
16 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] | 16 | I64, |
17 | pub enum IntBitness { | 17 | I128, |
18 | Xsize, | ||
19 | X8, | ||
20 | X16, | ||
21 | X32, | ||
22 | X64, | ||
23 | X128, | ||
24 | } | ||
25 | |||
26 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] | ||
27 | pub enum FloatBitness { | ||
28 | X32, | ||
29 | X64, | ||
30 | } | 18 | } |
31 | 19 | ||
32 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 20 | /// Different unsigned int types. |
33 | pub struct BuiltinInt { | 21 | #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
34 | pub signedness: Signedness, | 22 | pub enum BuiltinUint { |
35 | pub bitness: IntBitness, | 23 | Usize, |
24 | U8, | ||
25 | U16, | ||
26 | U32, | ||
27 | U64, | ||
28 | U128, | ||
36 | } | 29 | } |
37 | 30 | ||
38 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 31 | #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
39 | pub struct BuiltinFloat { | 32 | pub enum BuiltinFloat { |
40 | pub bitness: FloatBitness, | 33 | F32, |
34 | F64, | ||
41 | } | 35 | } |
42 | 36 | ||
43 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 37 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -46,6 +40,7 @@ pub enum BuiltinType { | |||
46 | Bool, | 40 | Bool, |
47 | Str, | 41 | Str, |
48 | Int(BuiltinInt), | 42 | Int(BuiltinInt), |
43 | Uint(BuiltinUint), | ||
49 | Float(BuiltinFloat), | 44 | Float(BuiltinFloat), |
50 | } | 45 | } |
51 | 46 | ||
@@ -56,19 +51,19 @@ impl BuiltinType { | |||
56 | (name![bool], BuiltinType::Bool), | 51 | (name![bool], BuiltinType::Bool), |
57 | (name![str], BuiltinType::Str), | 52 | (name![str], BuiltinType::Str), |
58 | 53 | ||
59 | (name![isize], BuiltinType::Int(BuiltinInt::ISIZE)), | 54 | (name![isize], BuiltinType::Int(BuiltinInt::Isize)), |
60 | (name![i8], BuiltinType::Int(BuiltinInt::I8)), | 55 | (name![i8], BuiltinType::Int(BuiltinInt::I8)), |
61 | (name![i16], BuiltinType::Int(BuiltinInt::I16)), | 56 | (name![i16], BuiltinType::Int(BuiltinInt::I16)), |
62 | (name![i32], BuiltinType::Int(BuiltinInt::I32)), | 57 | (name![i32], BuiltinType::Int(BuiltinInt::I32)), |
63 | (name![i64], BuiltinType::Int(BuiltinInt::I64)), | 58 | (name![i64], BuiltinType::Int(BuiltinInt::I64)), |
64 | (name![i128], BuiltinType::Int(BuiltinInt::I128)), | 59 | (name![i128], BuiltinType::Int(BuiltinInt::I128)), |
65 | 60 | ||
66 | (name![usize], BuiltinType::Int(BuiltinInt::USIZE)), | 61 | (name![usize], BuiltinType::Uint(BuiltinUint::Usize)), |
67 | (name![u8], BuiltinType::Int(BuiltinInt::U8)), | 62 | (name![u8], BuiltinType::Uint(BuiltinUint::U8)), |
68 | (name![u16], BuiltinType::Int(BuiltinInt::U16)), | 63 | (name![u16], BuiltinType::Uint(BuiltinUint::U16)), |
69 | (name![u32], BuiltinType::Int(BuiltinInt::U32)), | 64 | (name![u32], BuiltinType::Uint(BuiltinUint::U32)), |
70 | (name![u64], BuiltinType::Int(BuiltinInt::U64)), | 65 | (name![u64], BuiltinType::Uint(BuiltinUint::U64)), |
71 | (name![u128], BuiltinType::Int(BuiltinInt::U128)), | 66 | (name![u128], BuiltinType::Uint(BuiltinUint::U128)), |
72 | 67 | ||
73 | (name![f32], BuiltinType::Float(BuiltinFloat::F32)), | 68 | (name![f32], BuiltinType::Float(BuiltinFloat::F32)), |
74 | (name![f64], BuiltinType::Float(BuiltinFloat::F64)), | 69 | (name![f64], BuiltinType::Float(BuiltinFloat::F64)), |
@@ -81,24 +76,25 @@ impl AsName for BuiltinType { | |||
81 | BuiltinType::Char => name![char], | 76 | BuiltinType::Char => name![char], |
82 | BuiltinType::Bool => name![bool], | 77 | BuiltinType::Bool => name![bool], |
83 | BuiltinType::Str => name![str], | 78 | BuiltinType::Str => name![str], |
84 | BuiltinType::Int(BuiltinInt { signedness, bitness }) => match (signedness, bitness) { | 79 | BuiltinType::Int(it) => match it { |
85 | (Signedness::Signed, IntBitness::Xsize) => name![isize], | 80 | BuiltinInt::Isize => name![isize], |
86 | (Signedness::Signed, IntBitness::X8) => name![i8], | 81 | BuiltinInt::I8 => name![i8], |
87 | (Signedness::Signed, IntBitness::X16) => name![i16], | 82 | BuiltinInt::I16 => name![i16], |
88 | (Signedness::Signed, IntBitness::X32) => name![i32], | 83 | BuiltinInt::I32 => name![i32], |
89 | (Signedness::Signed, IntBitness::X64) => name![i64], | 84 | BuiltinInt::I64 => name![i64], |
90 | (Signedness::Signed, IntBitness::X128) => name![i128], | 85 | BuiltinInt::I128 => name![i128], |
91 | 86 | }, | |
92 | (Signedness::Unsigned, IntBitness::Xsize) => name![usize], | 87 | BuiltinType::Uint(it) => match it { |
93 | (Signedness::Unsigned, IntBitness::X8) => name![u8], | 88 | BuiltinUint::Usize => name![usize], |
94 | (Signedness::Unsigned, IntBitness::X16) => name![u16], | 89 | BuiltinUint::U8 => name![u8], |
95 | (Signedness::Unsigned, IntBitness::X32) => name![u32], | 90 | BuiltinUint::U16 => name![u16], |
96 | (Signedness::Unsigned, IntBitness::X64) => name![u64], | 91 | BuiltinUint::U32 => name![u32], |
97 | (Signedness::Unsigned, IntBitness::X128) => name![u128], | 92 | BuiltinUint::U64 => name![u64], |
93 | BuiltinUint::U128 => name![u128], | ||
98 | }, | 94 | }, |
99 | BuiltinType::Float(BuiltinFloat { bitness }) => match bitness { | 95 | BuiltinType::Float(it) => match it { |
100 | FloatBitness::X32 => name![f32], | 96 | BuiltinFloat::F32 => name![f32], |
101 | FloatBitness::X64 => name![f64], | 97 | BuiltinFloat::F64 => name![f64], |
102 | }, | 98 | }, |
103 | } | 99 | } |
104 | } | 100 | } |
@@ -113,31 +109,26 @@ impl fmt::Display for BuiltinType { | |||
113 | 109 | ||
114 | #[rustfmt::skip] | 110 | #[rustfmt::skip] |
115 | impl BuiltinInt { | 111 | impl BuiltinInt { |
116 | pub const ISIZE: BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::Xsize }; | ||
117 | pub const I8 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X8 }; | ||
118 | pub const I16 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X16 }; | ||
119 | pub const I32 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X32 }; | ||
120 | pub const I64 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X64 }; | ||
121 | pub const I128 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X128 }; | ||
122 | |||
123 | pub const USIZE: BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::Xsize }; | ||
124 | pub const U8 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X8 }; | ||
125 | pub const U16 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X16 }; | ||
126 | pub const U32 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X32 }; | ||
127 | pub const U64 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X64 }; | ||
128 | pub const U128 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X128 }; | ||
129 | |||
130 | |||
131 | pub fn from_suffix(suffix: &str) -> Option<BuiltinInt> { | 112 | pub fn from_suffix(suffix: &str) -> Option<BuiltinInt> { |
132 | let res = match suffix { | 113 | let res = match suffix { |
133 | "isize" => Self::ISIZE, | 114 | "isize" => Self::Isize, |
134 | "i8" => Self::I8, | 115 | "i8" => Self::I8, |
135 | "i16" => Self::I16, | 116 | "i16" => Self::I16, |
136 | "i32" => Self::I32, | 117 | "i32" => Self::I32, |
137 | "i64" => Self::I64, | 118 | "i64" => Self::I64, |
138 | "i128" => Self::I128, | 119 | "i128" => Self::I128, |
139 | 120 | ||
140 | "usize" => Self::USIZE, | 121 | _ => return None, |
122 | }; | ||
123 | Some(res) | ||
124 | } | ||
125 | } | ||
126 | |||
127 | #[rustfmt::skip] | ||
128 | impl BuiltinUint { | ||
129 | pub fn from_suffix(suffix: &str) -> Option<BuiltinUint> { | ||
130 | let res = match suffix { | ||
131 | "usize" => Self::Usize, | ||
141 | "u8" => Self::U8, | 132 | "u8" => Self::U8, |
142 | "u16" => Self::U16, | 133 | "u16" => Self::U16, |
143 | "u32" => Self::U32, | 134 | "u32" => Self::U32, |
@@ -152,9 +143,6 @@ impl BuiltinInt { | |||
152 | 143 | ||
153 | #[rustfmt::skip] | 144 | #[rustfmt::skip] |
154 | impl BuiltinFloat { | 145 | impl BuiltinFloat { |
155 | pub const F32: BuiltinFloat = BuiltinFloat { bitness: FloatBitness::X32 }; | ||
156 | pub const F64: BuiltinFloat = BuiltinFloat { bitness: FloatBitness::X64 }; | ||
157 | |||
158 | pub fn from_suffix(suffix: &str) -> Option<BuiltinFloat> { | 146 | pub fn from_suffix(suffix: &str) -> Option<BuiltinFloat> { |
159 | let res = match suffix { | 147 | let res = match suffix { |
160 | "f32" => BuiltinFloat::F32, | 148 | "f32" => BuiltinFloat::F32, |
diff --git a/crates/hir_def/src/diagnostics.rs b/crates/hir_def/src/diagnostics.rs index ab3f059ce..ac7474f63 100644 --- a/crates/hir_def/src/diagnostics.rs +++ b/crates/hir_def/src/diagnostics.rs | |||
@@ -95,6 +95,34 @@ impl Diagnostic for UnresolvedImport { | |||
95 | } | 95 | } |
96 | } | 96 | } |
97 | 97 | ||
98 | // Diagnostic: unresolved-macro-call | ||
99 | // | ||
100 | // This diagnostic is triggered if rust-analyzer is unable to resolove path to a | ||
101 | // macro in a macro invocation. | ||
102 | #[derive(Debug)] | ||
103 | pub struct UnresolvedMacroCall { | ||
104 | pub file: HirFileId, | ||
105 | pub node: AstPtr<ast::MacroCall>, | ||
106 | } | ||
107 | |||
108 | impl Diagnostic for UnresolvedMacroCall { | ||
109 | fn code(&self) -> DiagnosticCode { | ||
110 | DiagnosticCode("unresolved-macro-call") | ||
111 | } | ||
112 | fn message(&self) -> String { | ||
113 | "unresolved macro call".to_string() | ||
114 | } | ||
115 | fn display_source(&self) -> InFile<SyntaxNodePtr> { | ||
116 | InFile::new(self.file, self.node.clone().into()) | ||
117 | } | ||
118 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | ||
119 | self | ||
120 | } | ||
121 | fn is_experimental(&self) -> bool { | ||
122 | true | ||
123 | } | ||
124 | } | ||
125 | |||
98 | // Diagnostic: inactive-code | 126 | // Diagnostic: inactive-code |
99 | // | 127 | // |
100 | // This diagnostic is shown for code with inactive `#[cfg]` attributes. | 128 | // This diagnostic is shown for code with inactive `#[cfg]` attributes. |
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs index 4d72eaeaf..24be93773 100644 --- a/crates/hir_def/src/expr.rs +++ b/crates/hir_def/src/expr.rs | |||
@@ -17,7 +17,7 @@ use la_arena::{Idx, RawIdx}; | |||
17 | use syntax::ast::RangeOp; | 17 | use syntax::ast::RangeOp; |
18 | 18 | ||
19 | use crate::{ | 19 | use crate::{ |
20 | builtin_type::{BuiltinFloat, BuiltinInt}, | 20 | builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}, |
21 | path::{GenericArgs, Path}, | 21 | path::{GenericArgs, Path}, |
22 | type_ref::{Mutability, Rawness, TypeRef}, | 22 | type_ref::{Mutability, Rawness, TypeRef}, |
23 | BlockId, | 23 | BlockId, |
@@ -43,6 +43,7 @@ pub enum Literal { | |||
43 | Char(char), | 43 | Char(char), |
44 | Bool(bool), | 44 | Bool(bool), |
45 | Int(u64, Option<BuiltinInt>), | 45 | Int(u64, Option<BuiltinInt>), |
46 | Uint(u64, Option<BuiltinUint>), | ||
46 | Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq | 47 | Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq |
47 | } | 48 | } |
48 | 49 | ||
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs index 5e2a711b8..3e19a7702 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs | |||
@@ -1,5 +1,7 @@ | |||
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::iter; | ||
4 | |||
3 | use hir_expand::name::{known, AsName, Name}; | 5 | use hir_expand::name::{known, AsName, Name}; |
4 | use rustc_hash::FxHashSet; | 6 | use rustc_hash::FxHashSet; |
5 | use test_utils::mark; | 7 | use test_utils::mark; |
@@ -95,7 +97,7 @@ fn find_path_inner( | |||
95 | item: ItemInNs, | 97 | item: ItemInNs, |
96 | from: ModuleId, | 98 | from: ModuleId, |
97 | max_len: usize, | 99 | max_len: usize, |
98 | prefixed: Option<PrefixKind>, | 100 | mut prefixed: Option<PrefixKind>, |
99 | ) -> Option<ModPath> { | 101 | ) -> Option<ModPath> { |
100 | if max_len == 0 { | 102 | if max_len == 0 { |
101 | return None; | 103 | return None; |
@@ -114,8 +116,9 @@ fn find_path_inner( | |||
114 | } | 116 | } |
115 | 117 | ||
116 | // - if the item is the crate root, return `crate` | 118 | // - if the item is the crate root, return `crate` |
117 | let root = def_map.module_id(def_map.root()); | 119 | let root = def_map.crate_root(db); |
118 | if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) && def_map.block_id().is_none() { | 120 | if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) && def_map.block_id().is_none() { |
121 | // FIXME: the `block_id()` check should be unnecessary, but affects the result | ||
119 | return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); | 122 | return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); |
120 | } | 123 | } |
121 | 124 | ||
@@ -165,7 +168,7 @@ fn find_path_inner( | |||
165 | 168 | ||
166 | // - otherwise, look for modules containing (reexporting) it and import it from one of those | 169 | // - otherwise, look for modules containing (reexporting) it and import it from one of those |
167 | 170 | ||
168 | let crate_root = def_map.module_id(def_map.root()); | 171 | let crate_root = def_map.crate_root(db); |
169 | let crate_attrs = db.attrs(crate_root.into()); | 172 | let crate_attrs = db.attrs(crate_root.into()); |
170 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); | 173 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); |
171 | let mut best_path = None; | 174 | let mut best_path = None; |
@@ -228,12 +231,16 @@ fn find_path_inner( | |||
228 | } | 231 | } |
229 | } | 232 | } |
230 | 233 | ||
231 | if let Some(mut prefix) = prefixed.map(PrefixKind::prefix) { | 234 | // If the item is declared inside a block expression, don't use a prefix, as we don't handle |
232 | if matches!(prefix, PathKind::Crate | PathKind::Super(0)) && def_map.block_id().is_some() { | 235 | // that correctly (FIXME). |
233 | // Inner items cannot be referred to via `crate::` or `self::` paths. | 236 | if let Some(item_module) = item.as_module_def_id().and_then(|did| did.module(db)) { |
234 | prefix = PathKind::Plain; | 237 | if item_module.def_map(db).block_id().is_some() && prefixed.is_some() { |
238 | mark::hit!(prefixed_in_block_expression); | ||
239 | prefixed = Some(PrefixKind::Plain); | ||
235 | } | 240 | } |
241 | } | ||
236 | 242 | ||
243 | if let Some(prefix) = prefixed.map(PrefixKind::prefix) { | ||
237 | best_path.or_else(|| { | 244 | best_path.or_else(|| { |
238 | scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name])) | 245 | scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name])) |
239 | }) | 246 | }) |
@@ -285,12 +292,12 @@ fn find_local_import_locations( | |||
285 | let data = &def_map[from.local_id]; | 292 | let data = &def_map[from.local_id]; |
286 | let mut worklist = | 293 | let mut worklist = |
287 | data.children.values().map(|child| def_map.module_id(*child)).collect::<Vec<_>>(); | 294 | data.children.values().map(|child| def_map.module_id(*child)).collect::<Vec<_>>(); |
288 | let mut parent = data.parent; | 295 | for ancestor in iter::successors(from.containing_module(db), |m| m.containing_module(db)) { |
289 | while let Some(p) = parent { | 296 | worklist.push(ancestor); |
290 | worklist.push(def_map.module_id(p)); | ||
291 | parent = def_map[p].parent; | ||
292 | } | 297 | } |
293 | 298 | ||
299 | let def_map = def_map.crate_root(db).def_map(db); | ||
300 | |||
294 | let mut seen: FxHashSet<_> = FxHashSet::default(); | 301 | let mut seen: FxHashSet<_> = FxHashSet::default(); |
295 | 302 | ||
296 | let mut locations = Vec::new(); | 303 | let mut locations = Vec::new(); |
@@ -301,7 +308,14 @@ fn find_local_import_locations( | |||
301 | 308 | ||
302 | let ext_def_map; | 309 | let ext_def_map; |
303 | let data = if module.krate == from.krate { | 310 | let data = if module.krate == from.krate { |
304 | &def_map[module.local_id] | 311 | if module.block.is_some() { |
312 | // Re-query the block's DefMap | ||
313 | ext_def_map = module.def_map(db); | ||
314 | &ext_def_map[module.local_id] | ||
315 | } else { | ||
316 | // Reuse the root DefMap | ||
317 | &def_map[module.local_id] | ||
318 | } | ||
305 | } else { | 319 | } else { |
306 | // The crate might reexport a module defined in another crate. | 320 | // The crate might reexport a module defined in another crate. |
307 | ext_def_map = module.def_map(db); | 321 | ext_def_map = module.def_map(db); |
@@ -828,6 +842,7 @@ mod tests { | |||
828 | 842 | ||
829 | #[test] | 843 | #[test] |
830 | fn inner_items_from_inner_module() { | 844 | fn inner_items_from_inner_module() { |
845 | mark::check!(prefixed_in_block_expression); | ||
831 | check_found_path( | 846 | check_found_path( |
832 | r#" | 847 | r#" |
833 | fn main() { | 848 | fn main() { |
@@ -869,4 +884,24 @@ mod tests { | |||
869 | "super::Struct", | 884 | "super::Struct", |
870 | ); | 885 | ); |
871 | } | 886 | } |
887 | |||
888 | #[test] | ||
889 | fn outer_items_with_inner_items_present() { | ||
890 | check_found_path( | ||
891 | r#" | ||
892 | mod module { | ||
893 | pub struct CompleteMe; | ||
894 | } | ||
895 | |||
896 | fn main() { | ||
897 | fn inner() {} | ||
898 | $0 | ||
899 | } | ||
900 | "#, | ||
901 | "module::CompleteMe", | ||
902 | "module::CompleteMe", | ||
903 | "crate::module::CompleteMe", | ||
904 | "self::module::CompleteMe", | ||
905 | ) | ||
906 | } | ||
872 | } | 907 | } |
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index ee46c3330..4e5daa2ff 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs | |||
@@ -12,8 +12,8 @@ use stdx::format_to; | |||
12 | use test_utils::mark; | 12 | use test_utils::mark; |
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
15 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, | 15 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ImplId, |
16 | LocalModuleId, Lookup, MacroDefId, ModuleDefId, ModuleId, TraitId, | 16 | LocalModuleId, MacroDefId, ModuleDefId, ModuleId, TraitId, |
17 | }; | 17 | }; |
18 | 18 | ||
19 | #[derive(Copy, Clone)] | 19 | #[derive(Copy, Clone)] |
@@ -375,19 +375,9 @@ impl ItemInNs { | |||
375 | 375 | ||
376 | /// Returns the crate defining this item (or `None` if `self` is built-in). | 376 | /// Returns the crate defining this item (or `None` if `self` is built-in). |
377 | pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> { | 377 | pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> { |
378 | Some(match self { | 378 | match self { |
379 | ItemInNs::Types(did) | ItemInNs::Values(did) => match did { | 379 | ItemInNs::Types(did) | ItemInNs::Values(did) => did.module(db).map(|m| m.krate), |
380 | ModuleDefId::ModuleId(id) => id.krate, | 380 | ItemInNs::Macros(id) => Some(id.krate), |
381 | ModuleDefId::FunctionId(id) => id.lookup(db).module(db).krate, | 381 | } |
382 | ModuleDefId::AdtId(id) => id.module(db).krate, | ||
383 | ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container.module(db).krate, | ||
384 | ModuleDefId::ConstId(id) => id.lookup(db).container.module(db).krate, | ||
385 | ModuleDefId::StaticId(id) => id.lookup(db).container.module(db).krate, | ||
386 | ModuleDefId::TraitId(id) => id.lookup(db).container.module(db).krate, | ||
387 | ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate, | ||
388 | ModuleDefId::BuiltinType(_) => return None, | ||
389 | }, | ||
390 | ItemInNs::Macros(id) => return Some(id.krate), | ||
391 | }) | ||
392 | } | 382 | } |
393 | } | 383 | } |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index b50923747..4498d94bb 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -57,8 +57,10 @@ use std::{ | |||
57 | 57 | ||
58 | use base_db::{impl_intern_key, salsa, CrateId}; | 58 | use base_db::{impl_intern_key, salsa, CrateId}; |
59 | use hir_expand::{ | 59 | use hir_expand::{ |
60 | ast_id_map::FileAstId, eager::expand_eager_macro, hygiene::Hygiene, AstId, HirFileId, InFile, | 60 | ast_id_map::FileAstId, |
61 | MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | 61 | eager::{expand_eager_macro, ErrorEmitted}, |
62 | hygiene::Hygiene, | ||
63 | AstId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | ||
62 | }; | 64 | }; |
63 | use la_arena::Idx; | 65 | use la_arena::Idx; |
64 | use nameres::DefMap; | 66 | use nameres::DefMap; |
@@ -95,6 +97,10 @@ impl ModuleId { | |||
95 | pub fn krate(&self) -> CrateId { | 97 | pub fn krate(&self) -> CrateId { |
96 | self.krate | 98 | self.krate |
97 | } | 99 | } |
100 | |||
101 | pub fn containing_module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> { | ||
102 | self.def_map(db).containing_module(self.local_id) | ||
103 | } | ||
98 | } | 104 | } |
99 | 105 | ||
100 | /// An ID of a module, **local** to a specific crate | 106 | /// An ID of a module, **local** to a specific crate |
@@ -527,6 +533,25 @@ impl HasModule for StaticLoc { | |||
527 | } | 533 | } |
528 | } | 534 | } |
529 | 535 | ||
536 | impl ModuleDefId { | ||
537 | /// Returns the module containing `self` (or `self`, if `self` is itself a module). | ||
538 | /// | ||
539 | /// Returns `None` if `self` refers to a primitive type. | ||
540 | pub fn module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> { | ||
541 | Some(match self { | ||
542 | ModuleDefId::ModuleId(id) => *id, | ||
543 | ModuleDefId::FunctionId(id) => id.lookup(db).module(db), | ||
544 | ModuleDefId::AdtId(id) => id.module(db), | ||
545 | ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container.module(db), | ||
546 | ModuleDefId::ConstId(id) => id.lookup(db).container.module(db), | ||
547 | ModuleDefId::StaticId(id) => id.lookup(db).container.module(db), | ||
548 | ModuleDefId::TraitId(id) => id.lookup(db).container.module(db), | ||
549 | ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db), | ||
550 | ModuleDefId::BuiltinType(_) => return None, | ||
551 | }) | ||
552 | } | ||
553 | } | ||
554 | |||
530 | impl AttrDefId { | 555 | impl AttrDefId { |
531 | pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId { | 556 | pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId { |
532 | match self { | 557 | match self { |
@@ -592,8 +617,15 @@ impl AsMacroCall for InFile<&ast::MacroCall> { | |||
592 | error_sink(mbe::ExpandError::Other("malformed macro invocation".into())); | 617 | error_sink(mbe::ExpandError::Other("malformed macro invocation".into())); |
593 | } | 618 | } |
594 | 619 | ||
595 | AstIdWithPath::new(ast_id.file_id, ast_id.value, path?) | 620 | macro_call_as_call_id( |
596 | .as_call_id_with_errors(db, krate, resolver, error_sink) | 621 | &AstIdWithPath::new(ast_id.file_id, ast_id.value, path?), |
622 | db, | ||
623 | krate, | ||
624 | resolver, | ||
625 | error_sink, | ||
626 | ) | ||
627 | .ok()? | ||
628 | .ok() | ||
597 | } | 629 | } |
598 | } | 630 | } |
599 | 631 | ||
@@ -610,61 +642,50 @@ impl<T: ast::AstNode> AstIdWithPath<T> { | |||
610 | } | 642 | } |
611 | } | 643 | } |
612 | 644 | ||
613 | impl AsMacroCall for AstIdWithPath<ast::MacroCall> { | 645 | struct UnresolvedMacro; |
614 | fn as_call_id_with_errors( | 646 | |
615 | &self, | 647 | fn macro_call_as_call_id( |
616 | db: &dyn db::DefDatabase, | 648 | call: &AstIdWithPath<ast::MacroCall>, |
617 | krate: CrateId, | 649 | db: &dyn db::DefDatabase, |
618 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | 650 | krate: CrateId, |
619 | error_sink: &mut dyn FnMut(mbe::ExpandError), | 651 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, |
620 | ) -> Option<MacroCallId> { | 652 | error_sink: &mut dyn FnMut(mbe::ExpandError), |
621 | let def: MacroDefId = resolver(self.path.clone()).or_else(|| { | 653 | ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> { |
622 | error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path))); | 654 | let def: MacroDefId = resolver(call.path.clone()).ok_or(UnresolvedMacro)?; |
623 | None | 655 | |
624 | })?; | 656 | let res = if let MacroDefKind::BuiltInEager(_) = def.kind { |
625 | 657 | let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db.upcast())); | |
626 | if let MacroDefKind::BuiltInEager(_) = def.kind { | 658 | let hygiene = Hygiene::new(db.upcast(), call.ast_id.file_id); |
627 | let macro_call = InFile::new(self.ast_id.file_id, self.ast_id.to_node(db.upcast())); | 659 | |
628 | let hygiene = Hygiene::new(db.upcast(), self.ast_id.file_id); | 660 | expand_eager_macro( |
629 | 661 | db.upcast(), | |
630 | Some( | 662 | krate, |
631 | expand_eager_macro( | 663 | macro_call, |
632 | db.upcast(), | 664 | def, |
633 | krate, | 665 | &|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?), |
634 | macro_call, | 666 | error_sink, |
635 | def, | 667 | ) |
636 | &|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?), | 668 | .map(MacroCallId::from) |
637 | error_sink, | 669 | } else { |
638 | ) | 670 | Ok(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(call.ast_id)).into()) |
639 | .ok()? | 671 | }; |
640 | .into(), | 672 | Ok(res) |
641 | ) | ||
642 | } else { | ||
643 | Some(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(self.ast_id)).into()) | ||
644 | } | ||
645 | } | ||
646 | } | 673 | } |
647 | 674 | ||
648 | impl AsMacroCall for AstIdWithPath<ast::Item> { | 675 | fn item_attr_as_call_id( |
649 | fn as_call_id_with_errors( | 676 | item_attr: &AstIdWithPath<ast::Item>, |
650 | &self, | 677 | db: &dyn db::DefDatabase, |
651 | db: &dyn db::DefDatabase, | 678 | krate: CrateId, |
652 | krate: CrateId, | 679 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, |
653 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | 680 | ) -> Result<MacroCallId, UnresolvedMacro> { |
654 | error_sink: &mut dyn FnMut(mbe::ExpandError), | 681 | let def: MacroDefId = resolver(item_attr.path.clone()).ok_or(UnresolvedMacro)?; |
655 | ) -> Option<MacroCallId> { | 682 | let last_segment = item_attr.path.segments().last().ok_or(UnresolvedMacro)?; |
656 | let def: MacroDefId = resolver(self.path.clone()).or_else(|| { | 683 | let res = def |
657 | error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path))); | 684 | .as_lazy_macro( |
658 | None | 685 | db.upcast(), |
659 | })?; | 686 | krate, |
660 | 687 | MacroCallKind::Attr(item_attr.ast_id, last_segment.to_string()), | |
661 | Some( | ||
662 | def.as_lazy_macro( | ||
663 | db.upcast(), | ||
664 | krate, | ||
665 | MacroCallKind::Attr(self.ast_id, self.path.segments().last()?.to_string()), | ||
666 | ) | ||
667 | .into(), | ||
668 | ) | 688 | ) |
669 | } | 689 | .into(); |
690 | Ok(res) | ||
670 | } | 691 | } |
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index f92232eb3..003d668ca 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -343,6 +343,18 @@ impl DefMap { | |||
343 | Some(self.block?.parent) | 343 | Some(self.block?.parent) |
344 | } | 344 | } |
345 | 345 | ||
346 | /// Returns the module containing `local_mod`, either the parent `mod`, or the module containing | ||
347 | /// the block, if `self` corresponds to a block expression. | ||
348 | pub fn containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId> { | ||
349 | match &self[local_mod].parent { | ||
350 | Some(parent) => Some(self.module_id(*parent)), | ||
351 | None => match &self.block { | ||
352 | Some(block) => Some(block.parent), | ||
353 | None => None, | ||
354 | }, | ||
355 | } | ||
356 | } | ||
357 | |||
346 | // FIXME: this can use some more human-readable format (ideally, an IR | 358 | // FIXME: this can use some more human-readable format (ideally, an IR |
347 | // even), as this should be a great debugging aid. | 359 | // even), as this should be a great debugging aid. |
348 | pub fn dump(&self, db: &dyn DefDatabase) -> String { | 360 | pub fn dump(&self, db: &dyn DefDatabase) -> String { |
@@ -417,6 +429,8 @@ mod diagnostics { | |||
417 | 429 | ||
418 | UnresolvedProcMacro { ast: MacroCallKind }, | 430 | UnresolvedProcMacro { ast: MacroCallKind }, |
419 | 431 | ||
432 | UnresolvedMacroCall { ast: AstId<ast::MacroCall> }, | ||
433 | |||
420 | MacroError { ast: MacroCallKind, message: String }, | 434 | MacroError { ast: MacroCallKind, message: String }, |
421 | } | 435 | } |
422 | 436 | ||
@@ -477,6 +491,13 @@ mod diagnostics { | |||
477 | Self { in_module: container, kind: DiagnosticKind::MacroError { ast, message } } | 491 | Self { in_module: container, kind: DiagnosticKind::MacroError { ast, message } } |
478 | } | 492 | } |
479 | 493 | ||
494 | pub(super) fn unresolved_macro_call( | ||
495 | container: LocalModuleId, | ||
496 | ast: AstId<ast::MacroCall>, | ||
497 | ) -> Self { | ||
498 | Self { in_module: container, kind: DiagnosticKind::UnresolvedMacroCall { ast } } | ||
499 | } | ||
500 | |||
480 | pub(super) fn add_to( | 501 | pub(super) fn add_to( |
481 | &self, | 502 | &self, |
482 | db: &dyn DefDatabase, | 503 | db: &dyn DefDatabase, |
@@ -589,6 +610,11 @@ mod diagnostics { | |||
589 | }); | 610 | }); |
590 | } | 611 | } |
591 | 612 | ||
613 | DiagnosticKind::UnresolvedMacroCall { ast } => { | ||
614 | let node = ast.to_node(db.upcast()); | ||
615 | sink.push(UnresolvedMacroCall { file: ast.file_id, node: AstPtr::new(&node) }); | ||
616 | } | ||
617 | |||
592 | DiagnosticKind::MacroError { ast, message } => { | 618 | DiagnosticKind::MacroError { ast, message } => { |
593 | let (file, ast) = match ast { | 619 | let (file, ast) = match ast { |
594 | MacroCallKind::FnLike(ast) => { | 620 | MacroCallKind::FnLike(ast) => { |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 9996a0807..e51d89b43 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -13,7 +13,7 @@ use hir_expand::{ | |||
13 | builtin_macro::find_builtin_macro, | 13 | builtin_macro::find_builtin_macro, |
14 | name::{AsName, Name}, | 14 | name::{AsName, Name}, |
15 | proc_macro::ProcMacroExpander, | 15 | proc_macro::ProcMacroExpander, |
16 | HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | 16 | HirFileId, MacroCallId, MacroDefId, MacroDefKind, |
17 | }; | 17 | }; |
18 | use hir_expand::{InFile, MacroCallLoc}; | 18 | use hir_expand::{InFile, MacroCallLoc}; |
19 | use rustc_hash::{FxHashMap, FxHashSet}; | 19 | use rustc_hash::{FxHashMap, FxHashSet}; |
@@ -24,11 +24,13 @@ use tt::{Leaf, TokenTree}; | |||
24 | use crate::{ | 24 | use crate::{ |
25 | attr::Attrs, | 25 | attr::Attrs, |
26 | db::DefDatabase, | 26 | db::DefDatabase, |
27 | item_attr_as_call_id, | ||
27 | item_scope::{ImportType, PerNsGlobImports}, | 28 | item_scope::{ImportType, PerNsGlobImports}, |
28 | item_tree::{ | 29 | item_tree::{ |
29 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, | 30 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, |
30 | StructDefKind, | 31 | StructDefKind, |
31 | }, | 32 | }, |
33 | macro_call_as_call_id, | ||
32 | nameres::{ | 34 | nameres::{ |
33 | diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, | 35 | diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, |
34 | BuiltinShadowMode, DefMap, ModuleData, ModuleOrigin, ResolveMode, | 36 | BuiltinShadowMode, DefMap, ModuleData, ModuleOrigin, ResolveMode, |
@@ -36,9 +38,9 @@ use crate::{ | |||
36 | path::{ImportAlias, ModPath, PathKind}, | 38 | path::{ImportAlias, ModPath, PathKind}, |
37 | per_ns::PerNs, | 39 | per_ns::PerNs, |
38 | visibility::{RawVisibility, Visibility}, | 40 | visibility::{RawVisibility, Visibility}, |
39 | AdtId, AsMacroCall, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, | 41 | AdtId, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, |
40 | FunctionLoc, ImplLoc, Intern, LocalModuleId, ModuleDefId, StaticLoc, StructLoc, TraitLoc, | 42 | ImplLoc, Intern, LocalModuleId, ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, |
41 | TypeAliasLoc, UnionLoc, | 43 | UnionLoc, UnresolvedMacro, |
42 | }; | 44 | }; |
43 | 45 | ||
44 | const GLOB_RECURSION_LIMIT: usize = 100; | 46 | const GLOB_RECURSION_LIMIT: usize = 100; |
@@ -790,8 +792,11 @@ impl DefCollector<'_> { | |||
790 | return false; | 792 | return false; |
791 | } | 793 | } |
792 | 794 | ||
793 | if let Some(call_id) = | 795 | match macro_call_as_call_id( |
794 | directive.ast_id.as_call_id(self.db, self.def_map.krate, |path| { | 796 | &directive.ast_id, |
797 | self.db, | ||
798 | self.def_map.krate, | ||
799 | |path| { | ||
795 | let resolved_res = self.def_map.resolve_path_fp_with_macro( | 800 | let resolved_res = self.def_map.resolve_path_fp_with_macro( |
796 | self.db, | 801 | self.db, |
797 | ResolveMode::Other, | 802 | ResolveMode::Other, |
@@ -800,24 +805,29 @@ impl DefCollector<'_> { | |||
800 | BuiltinShadowMode::Module, | 805 | BuiltinShadowMode::Module, |
801 | ); | 806 | ); |
802 | resolved_res.resolved_def.take_macros() | 807 | resolved_res.resolved_def.take_macros() |
803 | }) | 808 | }, |
804 | { | 809 | &mut |_err| (), |
805 | resolved.push((directive.module_id, call_id, directive.depth)); | 810 | ) { |
806 | res = ReachedFixedPoint::No; | 811 | Ok(Ok(call_id)) => { |
807 | return false; | 812 | resolved.push((directive.module_id, call_id, directive.depth)); |
813 | res = ReachedFixedPoint::No; | ||
814 | return false; | ||
815 | } | ||
816 | Err(UnresolvedMacro) | Ok(Err(_)) => {} | ||
808 | } | 817 | } |
809 | 818 | ||
810 | true | 819 | true |
811 | }); | 820 | }); |
812 | attribute_macros.retain(|directive| { | 821 | attribute_macros.retain(|directive| { |
813 | if let Some(call_id) = | 822 | match item_attr_as_call_id(&directive.ast_id, self.db, self.def_map.krate, |path| { |
814 | directive.ast_id.as_call_id(self.db, self.def_map.krate, |path| { | 823 | self.resolve_attribute_macro(&directive, &path) |
815 | self.resolve_attribute_macro(&directive, &path) | 824 | }) { |
816 | }) | 825 | Ok(call_id) => { |
817 | { | 826 | resolved.push((directive.module_id, call_id, 0)); |
818 | resolved.push((directive.module_id, call_id, 0)); | 827 | res = ReachedFixedPoint::No; |
819 | res = ReachedFixedPoint::No; | 828 | return false; |
820 | return false; | 829 | } |
830 | Err(UnresolvedMacro) => (), | ||
821 | } | 831 | } |
822 | 832 | ||
823 | true | 833 | true |
@@ -902,7 +912,8 @@ impl DefCollector<'_> { | |||
902 | 912 | ||
903 | for directive in &self.unexpanded_macros { | 913 | for directive in &self.unexpanded_macros { |
904 | let mut error = None; | 914 | let mut error = None; |
905 | directive.ast_id.as_call_id_with_errors( | 915 | match macro_call_as_call_id( |
916 | &directive.ast_id, | ||
906 | self.db, | 917 | self.db, |
907 | self.def_map.krate, | 918 | self.def_map.krate, |
908 | |path| { | 919 | |path| { |
@@ -918,15 +929,15 @@ impl DefCollector<'_> { | |||
918 | &mut |e| { | 929 | &mut |e| { |
919 | error.get_or_insert(e); | 930 | error.get_or_insert(e); |
920 | }, | 931 | }, |
921 | ); | 932 | ) { |
922 | 933 | Ok(_) => (), | |
923 | if let Some(err) = error { | 934 | Err(UnresolvedMacro) => { |
924 | self.def_map.diagnostics.push(DefDiagnostic::macro_error( | 935 | self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call( |
925 | directive.module_id, | 936 | directive.module_id, |
926 | MacroCallKind::FnLike(directive.ast_id.ast_id), | 937 | directive.ast_id.ast_id, |
927 | err.to_string(), | 938 | )); |
928 | )); | 939 | } |
929 | } | 940 | }; |
930 | } | 941 | } |
931 | 942 | ||
932 | // Emit diagnostics for all remaining unresolved imports. | 943 | // Emit diagnostics for all remaining unresolved imports. |
@@ -1446,8 +1457,11 @@ impl ModCollector<'_, '_> { | |||
1446 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); | 1457 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); |
1447 | 1458 | ||
1448 | // Case 1: try to resolve in legacy scope and expand macro_rules | 1459 | // Case 1: try to resolve in legacy scope and expand macro_rules |
1449 | if let Some(macro_call_id) = | 1460 | if let Ok(Ok(macro_call_id)) = macro_call_as_call_id( |
1450 | ast_id.as_call_id(self.def_collector.db, self.def_collector.def_map.krate, |path| { | 1461 | &ast_id, |
1462 | self.def_collector.db, | ||
1463 | self.def_collector.def_map.krate, | ||
1464 | |path| { | ||
1451 | path.as_ident().and_then(|name| { | 1465 | path.as_ident().and_then(|name| { |
1452 | self.def_collector.def_map.with_ancestor_maps( | 1466 | self.def_collector.def_map.with_ancestor_maps( |
1453 | self.def_collector.db, | 1467 | self.def_collector.db, |
@@ -1455,8 +1469,9 @@ impl ModCollector<'_, '_> { | |||
1455 | &mut |map, module| map[module].scope.get_legacy_macro(&name), | 1469 | &mut |map, module| map[module].scope.get_legacy_macro(&name), |
1456 | ) | 1470 | ) |
1457 | }) | 1471 | }) |
1458 | }) | 1472 | }, |
1459 | { | 1473 | &mut |_err| (), |
1474 | ) { | ||
1460 | self.def_collector.unexpanded_macros.push(MacroDirective { | 1475 | self.def_collector.unexpanded_macros.push(MacroDirective { |
1461 | module_id: self.module_id, | 1476 | module_id: self.module_id, |
1462 | ast_id, | 1477 | ast_id, |
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs index fdcdc23ae..dd1db0094 100644 --- a/crates/hir_def/src/nameres/path_resolution.rs +++ b/crates/hir_def/src/nameres/path_resolution.rs | |||
@@ -77,7 +77,7 @@ impl DefMap { | |||
77 | original_module: LocalModuleId, | 77 | original_module: LocalModuleId, |
78 | visibility: &RawVisibility, | 78 | visibility: &RawVisibility, |
79 | ) -> Option<Visibility> { | 79 | ) -> Option<Visibility> { |
80 | match visibility { | 80 | let mut vis = match visibility { |
81 | RawVisibility::Module(path) => { | 81 | RawVisibility::Module(path) => { |
82 | let (result, remaining) = | 82 | let (result, remaining) = |
83 | self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module); | 83 | self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module); |
@@ -86,15 +86,28 @@ impl DefMap { | |||
86 | } | 86 | } |
87 | let types = result.take_types()?; | 87 | let types = result.take_types()?; |
88 | match types { | 88 | match types { |
89 | ModuleDefId::ModuleId(m) => Some(Visibility::Module(m)), | 89 | ModuleDefId::ModuleId(m) => Visibility::Module(m), |
90 | _ => { | 90 | _ => { |
91 | // error: visibility needs to refer to module | 91 | // error: visibility needs to refer to module |
92 | None | 92 | return None; |
93 | } | 93 | } |
94 | } | 94 | } |
95 | } | 95 | } |
96 | RawVisibility::Public => Some(Visibility::Public), | 96 | RawVisibility::Public => Visibility::Public, |
97 | }; | ||
98 | |||
99 | // In block expressions, `self` normally refers to the containing non-block module, and | ||
100 | // `super` to its parent (etc.). However, visibilities must only refer to a module in the | ||
101 | // DefMap they're written in, so we restrict them when that happens. | ||
102 | if let Visibility::Module(m) = vis { | ||
103 | if self.block_id() != m.block { | ||
104 | mark::hit!(adjust_vis_in_block_def_map); | ||
105 | vis = Visibility::Module(self.module_id(self.root())); | ||
106 | log::debug!("visibility {:?} points outside DefMap, adjusting to {:?}", m, vis); | ||
107 | } | ||
97 | } | 108 | } |
109 | |||
110 | Some(vis) | ||
98 | } | 111 | } |
99 | 112 | ||
100 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change | 113 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change |
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index a469546c1..505493a74 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs | |||
@@ -101,8 +101,12 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
101 | break; | 101 | break; |
102 | } | 102 | } |
103 | ast::PathSegmentKind::SelfKw => { | 103 | ast::PathSegmentKind::SelfKw => { |
104 | kind = PathKind::Super(0); | 104 | // don't break out if `self` is the last segment of a path, this mean we got an |
105 | break; | 105 | // use tree like `foo::{self}` which we want to resolve as `foo` |
106 | if !segments.is_empty() { | ||
107 | kind = PathKind::Super(0); | ||
108 | break; | ||
109 | } | ||
106 | } | 110 | } |
107 | ast::PathSegmentKind::SuperKw => { | 111 | ast::PathSegmentKind::SuperKw => { |
108 | let nested_super_count = if let PathKind::Super(n) = kind { n } else { 0 }; | 112 | let nested_super_count = if let PathKind::Super(n) = kind { n } else { 0 }; |
@@ -117,6 +121,11 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
117 | segments.reverse(); | 121 | segments.reverse(); |
118 | generic_args.reverse(); | 122 | generic_args.reverse(); |
119 | 123 | ||
124 | if segments.is_empty() && kind == PathKind::Plain && type_anchor.is_none() { | ||
125 | // plain empty paths don't exist, this means we got a single `self` segment as our path | ||
126 | kind = PathKind::Super(0); | ||
127 | } | ||
128 | |||
120 | // handle local_inner_macros : | 129 | // handle local_inner_macros : |
121 | // Basically, even in rustc it is quite hacky: | 130 | // Basically, even in rustc it is quite hacky: |
122 | // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456 | 131 | // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456 |