aboutsummaryrefslogtreecommitdiff
path: root/crates/hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir/src')
-rw-r--r--crates/hir/src/diagnostics.rs232
-rw-r--r--crates/hir/src/display.rs6
-rw-r--r--crates/hir/src/lib.rs213
-rw-r--r--crates/hir/src/semantics.rs10
-rw-r--r--crates/hir/src/source_analyzer.rs6
5 files changed, 406 insertions, 61 deletions
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 414c3f35e..22ec7c6ac 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -3,13 +3,227 @@
3//! 3//!
4//! This probably isn't the best way to do this -- ideally, diagnistics should 4//! This probably isn't the best way to do this -- ideally, diagnistics should
5//! be expressed in terms of hir types themselves. 5//! be expressed in terms of hir types themselves.
6pub use hir_def::diagnostics::{ 6use std::any::Any;
7 InactiveCode, UnresolvedMacroCall, UnresolvedModule, UnresolvedProcMacro, 7
8}; 8use cfg::{CfgExpr, CfgOptions, DnfExpr};
9pub use hir_expand::diagnostics::{ 9use hir_def::path::ModPath;
10 Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder, 10use hir_expand::{HirFileId, InFile};
11}; 11use stdx::format_to;
12pub use hir_ty::diagnostics::{ 12use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange};
13 IncorrectCase, MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr, 13
14 NoSuchField, RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap, 14pub use hir_ty::{
15 diagnostics::{
16 IncorrectCase, MismatchedArgCount, MissingFields, MissingMatchArms,
17 MissingOkOrSomeInTailExpr, NoSuchField, RemoveThisSemicolon,
18 ReplaceFilterMapNextWithFindMap,
19 },
20 diagnostics_sink::{Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder},
15}; 21};
22
23// Diagnostic: unresolved-module
24//
25// This diagnostic is triggered if rust-analyzer is unable to discover referred module.
26#[derive(Debug)]
27pub struct UnresolvedModule {
28 pub file: HirFileId,
29 pub decl: AstPtr<ast::Module>,
30 pub candidate: String,
31}
32
33impl Diagnostic for UnresolvedModule {
34 fn code(&self) -> DiagnosticCode {
35 DiagnosticCode("unresolved-module")
36 }
37 fn message(&self) -> String {
38 "unresolved module".to_string()
39 }
40 fn display_source(&self) -> InFile<SyntaxNodePtr> {
41 InFile::new(self.file, self.decl.clone().into())
42 }
43 fn as_any(&self) -> &(dyn Any + Send + 'static) {
44 self
45 }
46}
47
48// Diagnostic: unresolved-extern-crate
49//
50// This diagnostic is triggered if rust-analyzer is unable to discover referred extern crate.
51#[derive(Debug)]
52pub struct UnresolvedExternCrate {
53 pub file: HirFileId,
54 pub item: AstPtr<ast::ExternCrate>,
55}
56
57impl Diagnostic for UnresolvedExternCrate {
58 fn code(&self) -> DiagnosticCode {
59 DiagnosticCode("unresolved-extern-crate")
60 }
61 fn message(&self) -> String {
62 "unresolved extern crate".to_string()
63 }
64 fn display_source(&self) -> InFile<SyntaxNodePtr> {
65 InFile::new(self.file, self.item.clone().into())
66 }
67 fn as_any(&self) -> &(dyn Any + Send + 'static) {
68 self
69 }
70}
71
72#[derive(Debug)]
73pub struct UnresolvedImport {
74 pub file: HirFileId,
75 pub node: AstPtr<ast::UseTree>,
76}
77
78impl Diagnostic for UnresolvedImport {
79 fn code(&self) -> DiagnosticCode {
80 DiagnosticCode("unresolved-import")
81 }
82 fn message(&self) -> String {
83 "unresolved import".to_string()
84 }
85 fn display_source(&self) -> InFile<SyntaxNodePtr> {
86 InFile::new(self.file, self.node.clone().into())
87 }
88 fn as_any(&self) -> &(dyn Any + Send + 'static) {
89 self
90 }
91 fn is_experimental(&self) -> bool {
92 // This currently results in false positives in the following cases:
93 // - `cfg_if!`-generated code in libstd (we don't load the sysroot correctly)
94 // - `core::arch` (we don't handle `#[path = "../<path>"]` correctly)
95 // - proc macros and/or proc macro generated code
96 true
97 }
98}
99
100// Diagnostic: unresolved-macro-call
101//
102// This diagnostic is triggered if rust-analyzer is unable to resolve the path to a
103// macro in a macro invocation.
104#[derive(Debug, Clone, Eq, PartialEq)]
105pub struct UnresolvedMacroCall {
106 pub file: HirFileId,
107 pub node: AstPtr<ast::MacroCall>,
108 pub path: ModPath,
109}
110
111impl Diagnostic for UnresolvedMacroCall {
112 fn code(&self) -> DiagnosticCode {
113 DiagnosticCode("unresolved-macro-call")
114 }
115 fn message(&self) -> String {
116 format!("unresolved macro `{}!`", self.path)
117 }
118 fn display_source(&self) -> InFile<SyntaxNodePtr> {
119 InFile::new(self.file, self.node.clone().into())
120 }
121 fn as_any(&self) -> &(dyn Any + Send + 'static) {
122 self
123 }
124 fn is_experimental(&self) -> bool {
125 true
126 }
127}
128
129// Diagnostic: inactive-code
130//
131// This diagnostic is shown for code with inactive `#[cfg]` attributes.
132#[derive(Debug, Clone, Eq, PartialEq)]
133pub struct InactiveCode {
134 pub file: HirFileId,
135 pub node: SyntaxNodePtr,
136 pub cfg: CfgExpr,
137 pub opts: CfgOptions,
138}
139
140impl Diagnostic for InactiveCode {
141 fn code(&self) -> DiagnosticCode {
142 DiagnosticCode("inactive-code")
143 }
144 fn message(&self) -> String {
145 let inactive = DnfExpr::new(self.cfg.clone()).why_inactive(&self.opts);
146 let mut buf = "code is inactive due to #[cfg] directives".to_string();
147
148 if let Some(inactive) = inactive {
149 format_to!(buf, ": {}", inactive);
150 }
151
152 buf
153 }
154 fn display_source(&self) -> InFile<SyntaxNodePtr> {
155 InFile::new(self.file, self.node.clone())
156 }
157 fn as_any(&self) -> &(dyn Any + Send + 'static) {
158 self
159 }
160}
161
162// Diagnostic: unresolved-proc-macro
163//
164// This diagnostic is shown when a procedural macro can not be found. This usually means that
165// procedural macro support is simply disabled (and hence is only a weak hint instead of an error),
166// but can also indicate project setup problems.
167//
168// If you are seeing a lot of "proc macro not expanded" warnings, you can add this option to the
169// `rust-analyzer.diagnostics.disabled` list to prevent them from showing. Alternatively you can
170// enable support for procedural macros (see `rust-analyzer.procMacro.enable`).
171#[derive(Debug, Clone, Eq, PartialEq)]
172pub struct UnresolvedProcMacro {
173 pub file: HirFileId,
174 pub node: SyntaxNodePtr,
175 /// If the diagnostic can be pinpointed more accurately than via `node`, this is the `TextRange`
176 /// to use instead.
177 pub precise_location: Option<TextRange>,
178 pub macro_name: Option<String>,
179}
180
181impl Diagnostic for UnresolvedProcMacro {
182 fn code(&self) -> DiagnosticCode {
183 DiagnosticCode("unresolved-proc-macro")
184 }
185
186 fn message(&self) -> String {
187 match &self.macro_name {
188 Some(name) => format!("proc macro `{}` not expanded", name),
189 None => "proc macro not expanded".to_string(),
190 }
191 }
192
193 fn display_source(&self) -> InFile<SyntaxNodePtr> {
194 InFile::new(self.file, self.node.clone())
195 }
196
197 fn as_any(&self) -> &(dyn Any + Send + 'static) {
198 self
199 }
200}
201
202// Diagnostic: macro-error
203//
204// This diagnostic is shown for macro expansion errors.
205#[derive(Debug, Clone, Eq, PartialEq)]
206pub struct MacroError {
207 pub file: HirFileId,
208 pub node: SyntaxNodePtr,
209 pub message: String,
210}
211
212impl Diagnostic for MacroError {
213 fn code(&self) -> DiagnosticCode {
214 DiagnosticCode("macro-error")
215 }
216 fn message(&self) -> String {
217 self.message.clone()
218 }
219 fn display_source(&self) -> InFile<SyntaxNodePtr> {
220 InFile::new(self.file, self.node.clone())
221 }
222 fn as_any(&self) -> &(dyn Any + Send + 'static) {
223 self
224 }
225 fn is_experimental(&self) -> bool {
226 // Newly added and not very well-tested, might contain false positives.
227 true
228 }
229}
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 508ac37c2..72f0d9b5f 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -92,7 +92,7 @@ impl HirDisplay for Function {
92 &data.ret_type 92 &data.ret_type
93 } else { 93 } else {
94 match &*data.ret_type { 94 match &*data.ret_type {
95 TypeRef::ImplTrait(bounds) => match &bounds[0] { 95 TypeRef::ImplTrait(bounds) => match bounds[0].as_ref() {
96 TypeBound::Path(path) => { 96 TypeBound::Path(path) => {
97 path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings 97 path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings
98 [0] 98 [0]
@@ -427,10 +427,6 @@ impl HirDisplay for Trait {
427 write!(f, "trait {}", data.name)?; 427 write!(f, "trait {}", data.name)?;
428 let def_id = GenericDefId::TraitId(self.id); 428 let def_id = GenericDefId::TraitId(self.id);
429 write_generic_params(def_id, f)?; 429 write_generic_params(def_id, f)?;
430 if !data.bounds.is_empty() {
431 write!(f, ": ")?;
432 f.write_joined(&*data.bounds, " + ")?;
433 }
434 write_where_clause(def_id, f)?; 430 write_where_clause(def_id, f)?;
435 Ok(()) 431 Ok(())
436 } 432 }
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index ca9a7f7fa..975ae4869 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -35,12 +35,18 @@ use std::{iter, sync::Arc};
35 35
36use arrayvec::ArrayVec; 36use arrayvec::ArrayVec;
37use base_db::{CrateDisplayName, CrateId, Edition, FileId}; 37use base_db::{CrateDisplayName, CrateId, Edition, FileId};
38use diagnostics::{
39 InactiveCode, MacroError, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall,
40 UnresolvedModule, UnresolvedProcMacro,
41};
38use either::Either; 42use either::Either;
39use hir_def::{ 43use hir_def::{
40 adt::{ReprKind, VariantData}, 44 adt::{ReprKind, VariantData},
45 body::BodyDiagnostic,
41 expr::{BindingAnnotation, LabelId, Pat, PatId}, 46 expr::{BindingAnnotation, LabelId, Pat, PatId},
42 item_tree::ItemTreeNode, 47 item_tree::ItemTreeNode,
43 lang_item::LangItemTarget, 48 lang_item::LangItemTarget,
49 nameres,
44 per_ns::PerNs, 50 per_ns::PerNs,
45 resolver::{HasResolver, Resolver}, 51 resolver::{HasResolver, Resolver},
46 src::HasSource as _, 52 src::HasSource as _,
@@ -50,11 +56,12 @@ use hir_def::{
50 LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, 56 LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
51 TypeParamId, UnionId, 57 TypeParamId, UnionId,
52}; 58};
53use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; 59use hir_expand::{name::name, MacroCallKind, MacroDefKind};
54use hir_ty::{ 60use hir_ty::{
55 autoderef, 61 autoderef,
56 consteval::ConstExt, 62 consteval::ConstExt,
57 could_unify, 63 could_unify,
64 diagnostics_sink::DiagnosticSink,
58 method_resolution::{self, def_crates, TyFingerprint}, 65 method_resolution::{self, def_crates, TyFingerprint},
59 primitive::UintTy, 66 primitive::UintTy,
60 subst_prefix, 67 subst_prefix,
@@ -65,11 +72,12 @@ use hir_ty::{
65 WhereClause, 72 WhereClause,
66}; 73};
67use itertools::Itertools; 74use itertools::Itertools;
75use nameres::diagnostics::DefDiagnosticKind;
68use rustc_hash::FxHashSet; 76use rustc_hash::FxHashSet;
69use stdx::{format_to, impl_from}; 77use stdx::{format_to, impl_from};
70use syntax::{ 78use syntax::{
71 ast::{self, AttrsOwner, NameOwner}, 79 ast::{self, AttrsOwner, NameOwner},
72 AstNode, SmolStr, 80 AstNode, AstPtr, SmolStr, SyntaxKind, SyntaxNodePtr,
73}; 81};
74use tt::{Ident, Leaf, Literal, TokenTree}; 82use tt::{Ident, Leaf, Literal, TokenTree};
75 83
@@ -442,7 +450,123 @@ impl Module {
442 format!("{:?}", self.name(db).map_or("<unknown>".into(), |name| name.to_string())) 450 format!("{:?}", self.name(db).map_or("<unknown>".into(), |name| name.to_string()))
443 }); 451 });
444 let def_map = self.id.def_map(db.upcast()); 452 let def_map = self.id.def_map(db.upcast());
445 def_map.add_diagnostics(db.upcast(), self.id.local_id, sink); 453 for diag in def_map.diagnostics() {
454 if diag.in_module != self.id.local_id {
455 // FIXME: This is accidentally quadratic.
456 continue;
457 }
458 match &diag.kind {
459 DefDiagnosticKind::UnresolvedModule { ast: declaration, candidate } => {
460 let decl = declaration.to_node(db.upcast());
461 sink.push(UnresolvedModule {
462 file: declaration.file_id,
463 decl: AstPtr::new(&decl),
464 candidate: candidate.clone(),
465 })
466 }
467 DefDiagnosticKind::UnresolvedExternCrate { ast } => {
468 let item = ast.to_node(db.upcast());
469 sink.push(UnresolvedExternCrate {
470 file: ast.file_id,
471 item: AstPtr::new(&item),
472 });
473 }
474
475 DefDiagnosticKind::UnresolvedImport { id, index } => {
476 let file_id = id.file_id();
477 let item_tree = id.item_tree(db.upcast());
478 let import = &item_tree[id.value];
479
480 let use_tree = import.use_tree_to_ast(db.upcast(), file_id, *index);
481 sink.push(UnresolvedImport { file: file_id, node: AstPtr::new(&use_tree) });
482 }
483
484 DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => {
485 let item = ast.to_node(db.upcast());
486 sink.push(InactiveCode {
487 file: ast.file_id,
488 node: AstPtr::new(&item).into(),
489 cfg: cfg.clone(),
490 opts: opts.clone(),
491 });
492 }
493
494 DefDiagnosticKind::UnresolvedProcMacro { ast } => {
495 let mut precise_location = None;
496 let (file, ast, name) = match ast {
497 MacroCallKind::FnLike { ast_id, .. } => {
498 let node = ast_id.to_node(db.upcast());
499 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None)
500 }
501 MacroCallKind::Derive { ast_id, derive_name, .. } => {
502 let node = ast_id.to_node(db.upcast());
503
504 // Compute the precise location of the macro name's token in the derive
505 // list.
506 // FIXME: This does not handle paths to the macro, but neither does the
507 // rest of r-a.
508 let derive_attrs =
509 node.attrs().filter_map(|attr| match attr.as_simple_call() {
510 Some((name, args)) if name == "derive" => Some(args),
511 _ => None,
512 });
513 'outer: for attr in derive_attrs {
514 let tokens =
515 attr.syntax().children_with_tokens().filter_map(|elem| {
516 match elem {
517 syntax::NodeOrToken::Node(_) => None,
518 syntax::NodeOrToken::Token(tok) => Some(tok),
519 }
520 });
521 for token in tokens {
522 if token.kind() == SyntaxKind::IDENT
523 && token.text() == derive_name.as_str()
524 {
525 precise_location = Some(token.text_range());
526 break 'outer;
527 }
528 }
529 }
530
531 (
532 ast_id.file_id,
533 SyntaxNodePtr::from(AstPtr::new(&node)),
534 Some(derive_name.clone()),
535 )
536 }
537 };
538 sink.push(UnresolvedProcMacro {
539 file,
540 node: ast,
541 precise_location,
542 macro_name: name,
543 });
544 }
545
546 DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
547 let node = ast.to_node(db.upcast());
548 sink.push(UnresolvedMacroCall {
549 file: ast.file_id,
550 node: AstPtr::new(&node),
551 path: path.clone(),
552 });
553 }
554
555 DefDiagnosticKind::MacroError { ast, message } => {
556 let (file, ast) = match ast {
557 MacroCallKind::FnLike { ast_id, .. } => {
558 let node = ast_id.to_node(db.upcast());
559 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)))
560 }
561 MacroCallKind::Derive { ast_id, .. } => {
562 let node = ast_id.to_node(db.upcast());
563 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)))
564 }
565 };
566 sink.push(MacroError { file, node: ast, message: message.clone() });
567 }
568 }
569 }
446 for decl in self.declarations(db) { 570 for decl in self.declarations(db) {
447 match decl { 571 match decl {
448 crate::ModuleDef::Function(f) => f.diagnostics(db, sink), 572 crate::ModuleDef::Function(f) => f.diagnostics(db, sink),
@@ -551,10 +675,6 @@ impl Struct {
551 Module { id: self.id.lookup(db.upcast()).container } 675 Module { id: self.id.lookup(db.upcast()).container }
552 } 676 }
553 677
554 pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
555 Some(self.module(db).krate())
556 }
557
558 pub fn name(self, db: &dyn HirDatabase) -> Name { 678 pub fn name(self, db: &dyn HirDatabase) -> Name {
559 db.struct_data(self.id).name.clone() 679 db.struct_data(self.id).name.clone()
560 } 680 }
@@ -639,10 +759,6 @@ impl Enum {
639 Module { id: self.id.lookup(db.upcast()).container } 759 Module { id: self.id.lookup(db.upcast()).container }
640 } 760 }
641 761
642 pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
643 Some(self.module(db).krate())
644 }
645
646 pub fn name(self, db: &dyn HirDatabase) -> Name { 762 pub fn name(self, db: &dyn HirDatabase) -> Name {
647 db.enum_data(self.id).name.clone() 763 db.enum_data(self.id).name.clone()
648 } 764 }
@@ -672,6 +788,7 @@ impl Variant {
672 pub fn module(self, db: &dyn HirDatabase) -> Module { 788 pub fn module(self, db: &dyn HirDatabase) -> Module {
673 self.parent.module(db) 789 self.parent.module(db)
674 } 790 }
791
675 pub fn parent_enum(self, _db: &dyn HirDatabase) -> Enum { 792 pub fn parent_enum(self, _db: &dyn HirDatabase) -> Enum {
676 self.parent 793 self.parent
677 } 794 }
@@ -728,10 +845,6 @@ impl Adt {
728 } 845 }
729 } 846 }
730 847
731 pub fn krate(self, db: &dyn HirDatabase) -> Crate {
732 self.module(db).krate()
733 }
734
735 pub fn name(self, db: &dyn HirDatabase) -> Name { 848 pub fn name(self, db: &dyn HirDatabase) -> Name {
736 match self { 849 match self {
737 Adt::Struct(s) => s.name(db), 850 Adt::Struct(s) => s.name(db),
@@ -820,10 +933,6 @@ impl Function {
820 self.id.lookup(db.upcast()).module(db.upcast()).into() 933 self.id.lookup(db.upcast()).module(db.upcast()).into()
821 } 934 }
822 935
823 pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
824 Some(self.module(db).krate())
825 }
826
827 pub fn name(self, db: &dyn HirDatabase) -> Name { 936 pub fn name(self, db: &dyn HirDatabase) -> Name {
828 db.function_data(self.id).name.clone() 937 db.function_data(self.id).name.clone()
829 } 938 }
@@ -880,7 +989,37 @@ impl Function {
880 989
881 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { 990 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
882 let krate = self.module(db).id.krate(); 991 let krate = self.module(db).id.krate();
883 hir_def::diagnostics::validate_body(db.upcast(), self.id.into(), sink); 992
993 let source_map = db.body_with_source_map(self.id.into()).1;
994 for diag in source_map.diagnostics() {
995 match diag {
996 BodyDiagnostic::InactiveCode { node, cfg, opts } => sink.push(InactiveCode {
997 file: node.file_id,
998 node: node.value.clone(),
999 cfg: cfg.clone(),
1000 opts: opts.clone(),
1001 }),
1002 BodyDiagnostic::MacroError { node, message } => sink.push(MacroError {
1003 file: node.file_id,
1004 node: node.value.clone().into(),
1005 message: message.to_string(),
1006 }),
1007 BodyDiagnostic::UnresolvedProcMacro { node } => sink.push(UnresolvedProcMacro {
1008 file: node.file_id,
1009 node: node.value.clone().into(),
1010 precise_location: None,
1011 macro_name: None,
1012 }),
1013 BodyDiagnostic::UnresolvedMacroCall { node, path } => {
1014 sink.push(UnresolvedMacroCall {
1015 file: node.file_id,
1016 node: node.value.clone(),
1017 path: path.clone(),
1018 })
1019 }
1020 }
1021 }
1022
884 hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink); 1023 hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink);
885 hir_ty::diagnostics::validate_body(db, self.id.into(), sink); 1024 hir_ty::diagnostics::validate_body(db, self.id.into(), sink);
886 } 1025 }
@@ -1013,10 +1152,6 @@ impl Const {
1013 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } 1152 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
1014 } 1153 }
1015 1154
1016 pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
1017 Some(self.module(db).krate())
1018 }
1019
1020 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { 1155 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
1021 db.const_data(self.id).name.clone() 1156 db.const_data(self.id).name.clone()
1022 } 1157 }
@@ -1044,10 +1179,6 @@ impl Static {
1044 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } 1179 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
1045 } 1180 }
1046 1181
1047 pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
1048 Some(self.module(db).krate())
1049 }
1050
1051 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { 1182 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
1052 db.static_data(self.id).name.clone() 1183 db.static_data(self.id).name.clone()
1053 } 1184 }
@@ -1111,10 +1242,6 @@ impl TypeAlias {
1111 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } 1242 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
1112 } 1243 }
1113 1244
1114 pub fn krate(self, db: &dyn HirDatabase) -> Crate {
1115 self.module(db).krate()
1116 }
1117
1118 pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> { 1245 pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> {
1119 db.type_alias_data(self.id).type_ref.as_deref().cloned() 1246 db.type_alias_data(self.id).type_ref.as_deref().cloned()
1120 } 1247 }
@@ -1155,10 +1282,16 @@ impl BuiltinType {
1155 1282
1156#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 1283#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1157pub enum MacroKind { 1284pub enum MacroKind {
1285 /// `macro_rules!` or Macros 2.0 macro.
1158 Declarative, 1286 Declarative,
1159 ProcMacro, 1287 /// A built-in or custom derive.
1160 Derive, 1288 Derive,
1289 /// A built-in function-like macro.
1161 BuiltIn, 1290 BuiltIn,
1291 /// A procedural attribute macro.
1292 Attr,
1293 /// A function-like procedural macro.
1294 ProcMacro,
1162} 1295}
1163 1296
1164#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 1297#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -1188,11 +1321,13 @@ impl MacroDef {
1188 pub fn kind(&self) -> MacroKind { 1321 pub fn kind(&self) -> MacroKind {
1189 match self.id.kind { 1322 match self.id.kind {
1190 MacroDefKind::Declarative(_) => MacroKind::Declarative, 1323 MacroDefKind::Declarative(_) => MacroKind::Declarative,
1191 MacroDefKind::BuiltIn(_, _) => MacroKind::BuiltIn, 1324 MacroDefKind::BuiltIn(_, _) | MacroDefKind::BuiltInEager(_, _) => MacroKind::BuiltIn,
1192 MacroDefKind::BuiltInDerive(_, _) => MacroKind::Derive, 1325 MacroDefKind::BuiltInDerive(_, _) => MacroKind::Derive,
1193 MacroDefKind::BuiltInEager(_, _) => MacroKind::BuiltIn, 1326 MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::CustomDerive, _) => {
1194 // FIXME might be a derive 1327 MacroKind::Derive
1195 MacroDefKind::ProcMacro(_, _) => MacroKind::ProcMacro, 1328 }
1329 MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::Attr, _) => MacroKind::Attr,
1330 MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::FuncLike, _) => MacroKind::ProcMacro,
1196 } 1331 }
1197 } 1332 }
1198} 1333}
@@ -1666,10 +1801,6 @@ impl Impl {
1666 self.id.lookup(db.upcast()).container.into() 1801 self.id.lookup(db.upcast()).container.into()
1667 } 1802 }
1668 1803
1669 pub fn krate(self, db: &dyn HirDatabase) -> Crate {
1670 Crate { id: self.module(db).id.krate() }
1671 }
1672
1673 pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> { 1804 pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> {
1674 let src = self.source(db)?; 1805 let src = self.source(db)?;
1675 let item = src.file_id.is_builtin_derive(db.upcast())?; 1806 let item = src.file_id.is_builtin_derive(db.upcast())?;
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 3aa467e3c..8d3c43d08 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -120,10 +120,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
120 pub fn speculative_expand( 120 pub fn speculative_expand(
121 &self, 121 &self,
122 actual_macro_call: &ast::MacroCall, 122 actual_macro_call: &ast::MacroCall,
123 hypothetical_args: &ast::TokenTree, 123 speculative_args: &ast::TokenTree,
124 token_to_map: SyntaxToken, 124 token_to_map: SyntaxToken,
125 ) -> Option<(SyntaxNode, SyntaxToken)> { 125 ) -> Option<(SyntaxNode, SyntaxToken)> {
126 self.imp.speculative_expand(actual_macro_call, hypothetical_args, token_to_map) 126 self.imp.speculative_expand(actual_macro_call, speculative_args, token_to_map)
127 } 127 }
128 128
129 pub fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken { 129 pub fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken {
@@ -335,7 +335,7 @@ impl<'db> SemanticsImpl<'db> {
335 fn speculative_expand( 335 fn speculative_expand(
336 &self, 336 &self,
337 actual_macro_call: &ast::MacroCall, 337 actual_macro_call: &ast::MacroCall,
338 hypothetical_args: &ast::TokenTree, 338 speculative_args: &ast::TokenTree,
339 token_to_map: SyntaxToken, 339 token_to_map: SyntaxToken,
340 ) -> Option<(SyntaxNode, SyntaxToken)> { 340 ) -> Option<(SyntaxNode, SyntaxToken)> {
341 let sa = self.analyze(actual_macro_call.syntax()); 341 let sa = self.analyze(actual_macro_call.syntax());
@@ -344,10 +344,10 @@ impl<'db> SemanticsImpl<'db> {
344 let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| { 344 let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| {
345 sa.resolver.resolve_path_as_macro(self.db.upcast(), &path) 345 sa.resolver.resolve_path_as_macro(self.db.upcast(), &path)
346 })?; 346 })?;
347 hir_expand::db::expand_hypothetical( 347 hir_expand::db::expand_speculative(
348 self.db.upcast(), 348 self.db.upcast(),
349 macro_call_id, 349 macro_call_id,
350 hypothetical_args, 350 speculative_args,
351 token_to_map, 351 token_to_map,
352 ) 352 )
353 } 353 }
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 3f940124c..37a050415 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -308,7 +308,11 @@ impl SourceAnalyzer {
308 } 308 }
309 } 309 }
310 310
311 resolve_hir_path_(db, &self.resolver, &hir_path, prefer_value_ns) 311 if parent().map_or(false, |it| ast::Visibility::can_cast(it.kind())) {
312 resolve_hir_path_qualifier(db, &self.resolver, &hir_path)
313 } else {
314 resolve_hir_path_(db, &self.resolver, &hir_path, prefer_value_ns)
315 }
312 } 316 }
313 317
314 pub(crate) fn record_literal_missing_fields( 318 pub(crate) fn record_literal_missing_fields(