aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def')
-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/lib.rs114
-rw-r--r--crates/hir_def/src/nameres.rs14
-rw-r--r--crates/hir_def/src/nameres/collector.rs81
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs21
10 files changed, 266 insertions, 175 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/lib.rs b/crates/hir_def/src/lib.rs
index b50923747..6802bc250 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;
@@ -592,8 +594,15 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
592 error_sink(mbe::ExpandError::Other("malformed macro invocation".into())); 594 error_sink(mbe::ExpandError::Other("malformed macro invocation".into()));
593 } 595 }
594 596
595 AstIdWithPath::new(ast_id.file_id, ast_id.value, path?) 597 macro_call_as_call_id(
596 .as_call_id_with_errors(db, krate, resolver, error_sink) 598 &AstIdWithPath::new(ast_id.file_id, ast_id.value, path?),
599 db,
600 krate,
601 resolver,
602 error_sink,
603 )
604 .ok()?
605 .ok()
597 } 606 }
598} 607}
599 608
@@ -610,61 +619,50 @@ impl<T: ast::AstNode> AstIdWithPath<T> {
610 } 619 }
611} 620}
612 621
613impl AsMacroCall for AstIdWithPath<ast::MacroCall> { 622struct UnresolvedMacro;
614 fn as_call_id_with_errors( 623
615 &self, 624fn macro_call_as_call_id(
616 db: &dyn db::DefDatabase, 625 call: &AstIdWithPath<ast::MacroCall>,
617 krate: CrateId, 626 db: &dyn db::DefDatabase,
618 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, 627 krate: CrateId,
619 error_sink: &mut dyn FnMut(mbe::ExpandError), 628 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
620 ) -> Option<MacroCallId> { 629 error_sink: &mut dyn FnMut(mbe::ExpandError),
621 let def: MacroDefId = resolver(self.path.clone()).or_else(|| { 630) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
622 error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path))); 631 let def: MacroDefId = resolver(call.path.clone()).ok_or(UnresolvedMacro)?;
623 None 632
624 })?; 633 let res = if let MacroDefKind::BuiltInEager(_) = def.kind {
625 634 let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db.upcast()));
626 if let MacroDefKind::BuiltInEager(_) = def.kind { 635 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())); 636
628 let hygiene = Hygiene::new(db.upcast(), self.ast_id.file_id); 637 expand_eager_macro(
629 638 db.upcast(),
630 Some( 639 krate,
631 expand_eager_macro( 640 macro_call,
632 db.upcast(), 641 def,
633 krate, 642 &|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?),
634 macro_call, 643 error_sink,
635 def, 644 )
636 &|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?), 645 .map(MacroCallId::from)
637 error_sink, 646 } else {
638 ) 647 Ok(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(call.ast_id)).into())
639 .ok()? 648 };
640 .into(), 649 Ok(res)
641 )
642 } else {
643 Some(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(self.ast_id)).into())
644 }
645 }
646} 650}
647 651
648impl AsMacroCall for AstIdWithPath<ast::Item> { 652fn item_attr_as_call_id(
649 fn as_call_id_with_errors( 653 item_attr: &AstIdWithPath<ast::Item>,
650 &self, 654 db: &dyn db::DefDatabase,
651 db: &dyn db::DefDatabase, 655 krate: CrateId,
652 krate: CrateId, 656 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
653 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, 657) -> Result<MacroCallId, UnresolvedMacro> {
654 error_sink: &mut dyn FnMut(mbe::ExpandError), 658 let def: MacroDefId = resolver(item_attr.path.clone()).ok_or(UnresolvedMacro)?;
655 ) -> Option<MacroCallId> { 659 let last_segment = item_attr.path.segments().last().ok_or(UnresolvedMacro)?;
656 let def: MacroDefId = resolver(self.path.clone()).or_else(|| { 660 let res = def
657 error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path))); 661 .as_lazy_macro(
658 None 662 db.upcast(),
659 })?; 663 krate,
660 664 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 ) 665 )
669 } 666 .into();
667 Ok(res)
670} 668}
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index f92232eb3..6a3456f2e 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -417,6 +417,8 @@ mod diagnostics {
417 417
418 UnresolvedProcMacro { ast: MacroCallKind }, 418 UnresolvedProcMacro { ast: MacroCallKind },
419 419
420 UnresolvedMacroCall { ast: AstId<ast::MacroCall> },
421
420 MacroError { ast: MacroCallKind, message: String }, 422 MacroError { ast: MacroCallKind, message: String },
421 } 423 }
422 424
@@ -477,6 +479,13 @@ mod diagnostics {
477 Self { in_module: container, kind: DiagnosticKind::MacroError { ast, message } } 479 Self { in_module: container, kind: DiagnosticKind::MacroError { ast, message } }
478 } 480 }
479 481
482 pub(super) fn unresolved_macro_call(
483 container: LocalModuleId,
484 ast: AstId<ast::MacroCall>,
485 ) -> Self {
486 Self { in_module: container, kind: DiagnosticKind::UnresolvedMacroCall { ast } }
487 }
488
480 pub(super) fn add_to( 489 pub(super) fn add_to(
481 &self, 490 &self,
482 db: &dyn DefDatabase, 491 db: &dyn DefDatabase,
@@ -589,6 +598,11 @@ mod diagnostics {
589 }); 598 });
590 } 599 }
591 600
601 DiagnosticKind::UnresolvedMacroCall { ast } => {
602 let node = ast.to_node(db.upcast());
603 sink.push(UnresolvedMacroCall { file: ast.file_id, node: AstPtr::new(&node) });
604 }
605
592 DiagnosticKind::MacroError { ast, message } => { 606 DiagnosticKind::MacroError { ast, message } => {
593 let (file, ast) = match ast { 607 let (file, ast) = match ast {
594 MacroCallKind::FnLike(ast) => { 608 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