aboutsummaryrefslogtreecommitdiff
path: root/crates/hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir')
-rw-r--r--crates/hir/src/diagnostics.rs256
-rw-r--r--crates/hir/src/display.rs6
-rw-r--r--crates/hir/src/lib.rs226
-rw-r--r--crates/hir/src/semantics.rs29
-rw-r--r--crates/hir/src/source_analyzer.rs15
5 files changed, 456 insertions, 76 deletions
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 414c3f35e..2cdbd172a 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -3,13 +3,251 @@
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}
230
231#[derive(Debug)]
232pub struct UnimplementedBuiltinMacro {
233 pub file: HirFileId,
234 pub node: SyntaxNodePtr,
235}
236
237impl Diagnostic for UnimplementedBuiltinMacro {
238 fn code(&self) -> DiagnosticCode {
239 DiagnosticCode("unimplemented-builtin-macro")
240 }
241
242 fn message(&self) -> String {
243 "unimplemented built-in macro".to_string()
244 }
245
246 fn display_source(&self) -> InFile<SyntaxNodePtr> {
247 InFile::new(self.file, self.node.clone())
248 }
249
250 fn as_any(&self) -> &(dyn Any + Send + 'static) {
251 self
252 }
253}
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 a7c42ca1e..d3ef29db4 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, UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport,
40 UnresolvedMacroCall, 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,131 @@ 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 DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
570 let node = ast.to_node(db.upcast());
571 // Must have a name, otherwise we wouldn't emit it.
572 let name = node.name().expect("unimplemented builtin macro with no name");
573 let ptr = SyntaxNodePtr::from(AstPtr::new(&name));
574 sink.push(UnimplementedBuiltinMacro { file: ast.file_id, node: ptr });
575 }
576 }
577 }
446 for decl in self.declarations(db) { 578 for decl in self.declarations(db) {
447 match decl { 579 match decl {
448 crate::ModuleDef::Function(f) => f.diagnostics(db, sink), 580 crate::ModuleDef::Function(f) => f.diagnostics(db, sink),
@@ -513,9 +645,8 @@ impl Field {
513 } 645 }
514 646
515 /// Returns the type as in the signature of the struct (i.e., with 647 /// Returns the type as in the signature of the struct (i.e., with
516 /// placeholder types for type parameters). This is good for showing 648 /// placeholder types for type parameters). Only use this in the context of
517 /// signature help, but not so good to actually get the type of the field 649 /// the field definition.
518 /// when you actually have a variable of the struct.
519 pub fn ty(&self, db: &dyn HirDatabase) -> Type { 650 pub fn ty(&self, db: &dyn HirDatabase) -> Type {
520 let var_id = self.parent.into(); 651 let var_id = self.parent.into();
521 let generic_def_id: GenericDefId = match self.parent { 652 let generic_def_id: GenericDefId = match self.parent {
@@ -552,10 +683,6 @@ impl Struct {
552 Module { id: self.id.lookup(db.upcast()).container } 683 Module { id: self.id.lookup(db.upcast()).container }
553 } 684 }
554 685
555 pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
556 Some(self.module(db).krate())
557 }
558
559 pub fn name(self, db: &dyn HirDatabase) -> Name { 686 pub fn name(self, db: &dyn HirDatabase) -> Name {
560 db.struct_data(self.id).name.clone() 687 db.struct_data(self.id).name.clone()
561 } 688 }
@@ -640,10 +767,6 @@ impl Enum {
640 Module { id: self.id.lookup(db.upcast()).container } 767 Module { id: self.id.lookup(db.upcast()).container }
641 } 768 }
642 769
643 pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
644 Some(self.module(db).krate())
645 }
646
647 pub fn name(self, db: &dyn HirDatabase) -> Name { 770 pub fn name(self, db: &dyn HirDatabase) -> Name {
648 db.enum_data(self.id).name.clone() 771 db.enum_data(self.id).name.clone()
649 } 772 }
@@ -673,6 +796,7 @@ impl Variant {
673 pub fn module(self, db: &dyn HirDatabase) -> Module { 796 pub fn module(self, db: &dyn HirDatabase) -> Module {
674 self.parent.module(db) 797 self.parent.module(db)
675 } 798 }
799
676 pub fn parent_enum(self, _db: &dyn HirDatabase) -> Enum { 800 pub fn parent_enum(self, _db: &dyn HirDatabase) -> Enum {
677 self.parent 801 self.parent
678 } 802 }
@@ -729,10 +853,6 @@ impl Adt {
729 } 853 }
730 } 854 }
731 855
732 pub fn krate(self, db: &dyn HirDatabase) -> Crate {
733 self.module(db).krate()
734 }
735
736 pub fn name(self, db: &dyn HirDatabase) -> Name { 856 pub fn name(self, db: &dyn HirDatabase) -> Name {
737 match self { 857 match self {
738 Adt::Struct(s) => s.name(db), 858 Adt::Struct(s) => s.name(db),
@@ -821,10 +941,6 @@ impl Function {
821 self.id.lookup(db.upcast()).module(db.upcast()).into() 941 self.id.lookup(db.upcast()).module(db.upcast()).into()
822 } 942 }
823 943
824 pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
825 Some(self.module(db).krate())
826 }
827
828 pub fn name(self, db: &dyn HirDatabase) -> Name { 944 pub fn name(self, db: &dyn HirDatabase) -> Name {
829 db.function_data(self.id).name.clone() 945 db.function_data(self.id).name.clone()
830 } 946 }
@@ -881,7 +997,37 @@ impl Function {
881 997
882 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { 998 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
883 let krate = self.module(db).id.krate(); 999 let krate = self.module(db).id.krate();
884 hir_def::diagnostics::validate_body(db.upcast(), self.id.into(), sink); 1000
1001 let source_map = db.body_with_source_map(self.id.into()).1;
1002 for diag in source_map.diagnostics() {
1003 match diag {
1004 BodyDiagnostic::InactiveCode { node, cfg, opts } => sink.push(InactiveCode {
1005 file: node.file_id,
1006 node: node.value.clone(),
1007 cfg: cfg.clone(),
1008 opts: opts.clone(),
1009 }),
1010 BodyDiagnostic::MacroError { node, message } => sink.push(MacroError {
1011 file: node.file_id,
1012 node: node.value.clone().into(),
1013 message: message.to_string(),
1014 }),
1015 BodyDiagnostic::UnresolvedProcMacro { node } => sink.push(UnresolvedProcMacro {
1016 file: node.file_id,
1017 node: node.value.clone().into(),
1018 precise_location: None,
1019 macro_name: None,
1020 }),
1021 BodyDiagnostic::UnresolvedMacroCall { node, path } => {
1022 sink.push(UnresolvedMacroCall {
1023 file: node.file_id,
1024 node: node.value.clone(),
1025 path: path.clone(),
1026 })
1027 }
1028 }
1029 }
1030
885 hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink); 1031 hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink);
886 hir_ty::diagnostics::validate_body(db, self.id.into(), sink); 1032 hir_ty::diagnostics::validate_body(db, self.id.into(), sink);
887 } 1033 }
@@ -1014,10 +1160,6 @@ impl Const {
1014 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } 1160 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
1015 } 1161 }
1016 1162
1017 pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
1018 Some(self.module(db).krate())
1019 }
1020
1021 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { 1163 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
1022 db.const_data(self.id).name.clone() 1164 db.const_data(self.id).name.clone()
1023 } 1165 }
@@ -1045,10 +1187,6 @@ impl Static {
1045 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } 1187 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
1046 } 1188 }
1047 1189
1048 pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
1049 Some(self.module(db).krate())
1050 }
1051
1052 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { 1190 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
1053 db.static_data(self.id).name.clone() 1191 db.static_data(self.id).name.clone()
1054 } 1192 }
@@ -1112,10 +1250,6 @@ impl TypeAlias {
1112 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } 1250 Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
1113 } 1251 }
1114 1252
1115 pub fn krate(self, db: &dyn HirDatabase) -> Crate {
1116 self.module(db).krate()
1117 }
1118
1119 pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> { 1253 pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> {
1120 db.type_alias_data(self.id).type_ref.as_deref().cloned() 1254 db.type_alias_data(self.id).type_ref.as_deref().cloned()
1121 } 1255 }
@@ -1156,10 +1290,16 @@ impl BuiltinType {
1156 1290
1157#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 1291#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1158pub enum MacroKind { 1292pub enum MacroKind {
1293 /// `macro_rules!` or Macros 2.0 macro.
1159 Declarative, 1294 Declarative,
1160 ProcMacro, 1295 /// A built-in or custom derive.
1161 Derive, 1296 Derive,
1297 /// A built-in function-like macro.
1162 BuiltIn, 1298 BuiltIn,
1299 /// A procedural attribute macro.
1300 Attr,
1301 /// A function-like procedural macro.
1302 ProcMacro,
1163} 1303}
1164 1304
1165#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 1305#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -1189,11 +1329,13 @@ impl MacroDef {
1189 pub fn kind(&self) -> MacroKind { 1329 pub fn kind(&self) -> MacroKind {
1190 match self.id.kind { 1330 match self.id.kind {
1191 MacroDefKind::Declarative(_) => MacroKind::Declarative, 1331 MacroDefKind::Declarative(_) => MacroKind::Declarative,
1192 MacroDefKind::BuiltIn(_, _) => MacroKind::BuiltIn, 1332 MacroDefKind::BuiltIn(_, _) | MacroDefKind::BuiltInEager(_, _) => MacroKind::BuiltIn,
1193 MacroDefKind::BuiltInDerive(_, _) => MacroKind::Derive, 1333 MacroDefKind::BuiltInDerive(_, _) => MacroKind::Derive,
1194 MacroDefKind::BuiltInEager(_, _) => MacroKind::BuiltIn, 1334 MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::CustomDerive, _) => {
1195 // FIXME might be a derive 1335 MacroKind::Derive
1196 MacroDefKind::ProcMacro(_, _) => MacroKind::ProcMacro, 1336 }
1337 MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::Attr, _) => MacroKind::Attr,
1338 MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::FuncLike, _) => MacroKind::ProcMacro,
1197 } 1339 }
1198 } 1340 }
1199} 1341}
@@ -1667,10 +1809,6 @@ impl Impl {
1667 self.id.lookup(db.upcast()).container.into() 1809 self.id.lookup(db.upcast()).container.into()
1668 } 1810 }
1669 1811
1670 pub fn krate(self, db: &dyn HirDatabase) -> Crate {
1671 Crate { id: self.module(db).id.krate() }
1672 }
1673
1674 pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> { 1812 pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> {
1675 let src = self.source(db)?; 1813 let src = self.source(db)?;
1676 let item = src.file_id.is_builtin_derive(db.upcast())?; 1814 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 1b5064b5a..c7f2c02e4 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -11,7 +11,7 @@ use hir_def::{
11 AsMacroCall, FunctionId, TraitId, VariantId, 11 AsMacroCall, FunctionId, TraitId, VariantId,
12}; 12};
13use hir_expand::{name::AsName, ExpansionInfo}; 13use hir_expand::{name::AsName, ExpansionInfo};
14use hir_ty::associated_type_shorthand_candidates; 14use hir_ty::{associated_type_shorthand_candidates, Interner};
15use itertools::Itertools; 15use itertools::Itertools;
16use rustc_hash::{FxHashMap, FxHashSet}; 16use rustc_hash::{FxHashMap, FxHashSet};
17use syntax::{ 17use syntax::{
@@ -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 {
@@ -227,7 +227,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
227 pub fn resolve_record_field( 227 pub fn resolve_record_field(
228 &self, 228 &self,
229 field: &ast::RecordExprField, 229 field: &ast::RecordExprField,
230 ) -> Option<(Field, Option<Local>)> { 230 ) -> Option<(Field, Option<Local>, Type)> {
231 self.imp.resolve_record_field(field) 231 self.imp.resolve_record_field(field)
232 } 232 }
233 233
@@ -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 }
@@ -361,7 +361,7 @@ impl<'db> SemanticsImpl<'db> {
361 let sa = self.analyze(&parent); 361 let sa = self.analyze(&parent);
362 362
363 let token = successors(Some(InFile::new(sa.file_id, token)), |token| { 363 let token = successors(Some(InFile::new(sa.file_id, token)), |token| {
364 self.db.check_canceled(); 364 self.db.unwind_if_cancelled();
365 let macro_call = token.value.ancestors().find_map(ast::MacroCall::cast)?; 365 let macro_call = token.value.ancestors().find_map(ast::MacroCall::cast)?;
366 let tt = macro_call.token_tree()?; 366 let tt = macro_call.token_tree()?;
367 if !tt.syntax().text_range().contains_range(token.value.text_range()) { 367 if !tt.syntax().text_range().contains_range(token.value.text_range()) {
@@ -501,14 +501,12 @@ impl<'db> SemanticsImpl<'db> {
501 } 501 }
502 502
503 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> { 503 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> {
504 self.analyze(call.syntax()).resolve_method_call(self.db, call) 504 self.analyze(call.syntax()).resolve_method_call(self.db, call).map(|(id, _)| id)
505 } 505 }
506 506
507 fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> { 507 fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
508 // FIXME: this erases Substs, we should instead record the correct 508 let (func, subst) = self.analyze(call.syntax()).resolve_method_call(self.db, call)?;
509 // substitution during inference and use that 509 let ty = self.db.value_ty(func.into()).substitute(&Interner, &subst);
510 let func = self.resolve_method_call(call)?;
511 let ty = hir_ty::TyBuilder::value_ty(self.db, func.into()).fill_with_unknown().build();
512 let resolver = self.analyze(call.syntax()).resolver; 510 let resolver = self.analyze(call.syntax()).resolver;
513 let ty = Type::new_with_resolver(self.db, &resolver, ty)?; 511 let ty = Type::new_with_resolver(self.db, &resolver, ty)?;
514 let mut res = ty.as_callable(self.db)?; 512 let mut res = ty.as_callable(self.db)?;
@@ -520,7 +518,10 @@ impl<'db> SemanticsImpl<'db> {
520 self.analyze(field.syntax()).resolve_field(self.db, field) 518 self.analyze(field.syntax()).resolve_field(self.db, field)
521 } 519 }
522 520
523 fn resolve_record_field(&self, field: &ast::RecordExprField) -> Option<(Field, Option<Local>)> { 521 fn resolve_record_field(
522 &self,
523 field: &ast::RecordExprField,
524 ) -> Option<(Field, Option<Local>, Type)> {
524 self.analyze(field.syntax()).resolve_record_field(self.db, field) 525 self.analyze(field.syntax()).resolve_record_field(self.db, field)
525 } 526 }
526 527
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 20753314d..37a050415 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -143,7 +143,7 @@ impl SourceAnalyzer {
143 &self, 143 &self,
144 db: &dyn HirDatabase, 144 db: &dyn HirDatabase,
145 call: &ast::MethodCallExpr, 145 call: &ast::MethodCallExpr,
146 ) -> Option<FunctionId> { 146 ) -> Option<(FunctionId, Substitution)> {
147 let expr_id = self.expr_id(db, &call.clone().into())?; 147 let expr_id = self.expr_id(db, &call.clone().into())?;
148 self.infer.as_ref()?.method_resolution(expr_id) 148 self.infer.as_ref()?.method_resolution(expr_id)
149 } 149 }
@@ -161,7 +161,7 @@ impl SourceAnalyzer {
161 &self, 161 &self,
162 db: &dyn HirDatabase, 162 db: &dyn HirDatabase,
163 field: &ast::RecordExprField, 163 field: &ast::RecordExprField,
164 ) -> Option<(Field, Option<Local>)> { 164 ) -> Option<(Field, Option<Local>, Type)> {
165 let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?; 165 let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
166 let expr = ast::Expr::from(record_expr); 166 let expr = ast::Expr::from(record_expr);
167 let expr_id = self.body_source_map.as_ref()?.node_expr(InFile::new(self.file_id, &expr))?; 167 let expr_id = self.body_source_map.as_ref()?.node_expr(InFile::new(self.file_id, &expr))?;
@@ -178,10 +178,13 @@ impl SourceAnalyzer {
178 _ => None, 178 _ => None,
179 } 179 }
180 }; 180 };
181 let (_, subst) = self.infer.as_ref()?.type_of_expr.get(expr_id)?.as_adt()?;
181 let variant = self.infer.as_ref()?.variant_resolution_for_expr(expr_id)?; 182 let variant = self.infer.as_ref()?.variant_resolution_for_expr(expr_id)?;
182 let variant_data = variant.variant_data(db.upcast()); 183 let variant_data = variant.variant_data(db.upcast());
183 let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? }; 184 let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? };
184 Some((field.into(), local)) 185 let field_ty =
186 db.field_types(variant).get(field.local_id)?.clone().substitute(&Interner, subst);
187 Some((field.into(), local, Type::new_with_resolver(db, &self.resolver, field_ty)?))
185 } 188 }
186 189
187 pub(crate) fn resolve_record_pat_field( 190 pub(crate) fn resolve_record_pat_field(
@@ -305,7 +308,11 @@ impl SourceAnalyzer {
305 } 308 }
306 } 309 }
307 310
308 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 }
309 } 316 }
310 317
311 pub(crate) fn record_literal_missing_fields( 318 pub(crate) fn record_literal_missing_fields(