aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r--crates/hir_def/src/body.rs2
-rw-r--r--crates/hir_def/src/body/lower.rs17
-rw-r--r--crates/hir_def/src/body/tests/block.rs29
-rw-r--r--crates/hir_def/src/builtin_type.rs132
-rw-r--r--crates/hir_def/src/diagnostics.rs28
-rw-r--r--crates/hir_def/src/expr.rs3
-rw-r--r--crates/hir_def/src/find_path.rs59
-rw-r--r--crates/hir_def/src/item_scope.rs22
-rw-r--r--crates/hir_def/src/lib.rs137
-rw-r--r--crates/hir_def/src/nameres.rs26
-rw-r--r--crates/hir_def/src/nameres/collector.rs81
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs21
-rw-r--r--crates/hir_def/src/path/lower.rs13
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;
24use crate::{ 24use 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]
264fn 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#"
270mod 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 @@
6use std::fmt; 6use std::fmt;
7 7
8use hir_expand::name::{name, AsName, Name}; 8use 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)]
11pub enum Signedness { 11pub 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,
17pub 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)]
27pub enum FloatBitness {
28 X32,
29 X64,
30} 18}
31 19
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 20/// Different unsigned int types.
33pub struct BuiltinInt { 21#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
34 pub signedness: Signedness, 22pub 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)]
39pub struct BuiltinFloat { 32pub 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]
115impl BuiltinInt { 111impl 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]
128impl 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]
154impl BuiltinFloat { 145impl 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)]
103pub struct UnresolvedMacroCall {
104 pub file: HirFileId,
105 pub node: AstPtr<ast::MacroCall>,
106}
107
108impl 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};
17use syntax::ast::RangeOp; 17use syntax::ast::RangeOp;
18 18
19use crate::{ 19use 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
3use std::iter;
4
3use hir_expand::name::{known, AsName, Name}; 5use hir_expand::name::{known, AsName, Name};
4use rustc_hash::FxHashSet; 6use rustc_hash::FxHashSet;
5use test_utils::mark; 7use 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;
12use test_utils::mark; 12use test_utils::mark;
13 13
14use crate::{ 14use 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
58use base_db::{impl_intern_key, salsa, CrateId}; 58use base_db::{impl_intern_key, salsa, CrateId};
59use hir_expand::{ 59use 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};
63use la_arena::Idx; 65use la_arena::Idx;
64use nameres::DefMap; 66use 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
536impl 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
530impl AttrDefId { 555impl 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
613impl AsMacroCall for AstIdWithPath<ast::MacroCall> { 645struct UnresolvedMacro;
614 fn as_call_id_with_errors( 646
615 &self, 647fn 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
648impl AsMacroCall for AstIdWithPath<ast::Item> { 675fn 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};
18use hir_expand::{InFile, MacroCallLoc}; 18use hir_expand::{InFile, MacroCallLoc};
19use rustc_hash::{FxHashMap, FxHashSet}; 19use rustc_hash::{FxHashMap, FxHashSet};
@@ -24,11 +24,13 @@ use tt::{Leaf, TokenTree};
24use crate::{ 24use 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
44const GLOB_RECURSION_LIMIT: usize = 100; 46const 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