aboutsummaryrefslogtreecommitdiff
path: root/crates/hir/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir/src/lib.rs')
-rw-r--r--crates/hir/src/lib.rs213
1 files changed, 172 insertions, 41 deletions
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())?;