diff options
Diffstat (limited to 'crates/hir/src/lib.rs')
-rw-r--r-- | crates/hir/src/lib.rs | 360 |
1 files changed, 257 insertions, 103 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 0bb3767c1..b7eabaabb 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -15,7 +15,7 @@ | |||
15 | //! | 15 | //! |
16 | //! `hir` is what insulates the "we don't know how to actually write an incremental compiler" | 16 | //! `hir` is what insulates the "we don't know how to actually write an incremental compiler" |
17 | //! from the ide with completions, hovers, etc. It is a (soft, internal) boundary: | 17 | //! from the ide with completions, hovers, etc. It is a (soft, internal) boundary: |
18 | //! https://www.tedinski.com/2018/02/06/system-boundaries.html. | 18 | //! <https://www.tedinski.com/2018/02/06/system-boundaries.html>. |
19 | 19 | ||
20 | #![recursion_limit = "512"] | 20 | #![recursion_limit = "512"] |
21 | 21 | ||
@@ -35,14 +35,10 @@ use std::{iter, sync::Arc}; | |||
35 | 35 | ||
36 | use arrayvec::ArrayVec; | 36 | use arrayvec::ArrayVec; |
37 | use base_db::{CrateDisplayName, CrateId, Edition, FileId}; | 37 | use base_db::{CrateDisplayName, CrateId, Edition, FileId}; |
38 | use diagnostics::{ | ||
39 | InactiveCode, MacroError, UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, | ||
40 | UnresolvedMacroCall, UnresolvedModule, UnresolvedProcMacro, | ||
41 | }; | ||
42 | use either::Either; | 38 | use either::Either; |
43 | use hir_def::{ | 39 | use hir_def::{ |
44 | adt::{ReprKind, VariantData}, | 40 | adt::{ReprKind, VariantData}, |
45 | body::BodyDiagnostic, | 41 | body::{BodyDiagnostic, SyntheticSyntax}, |
46 | expr::{BindingAnnotation, LabelId, Pat, PatId}, | 42 | expr::{BindingAnnotation, LabelId, Pat, PatId}, |
47 | item_tree::ItemTreeNode, | 43 | item_tree::ItemTreeNode, |
48 | lang_item::LangItemTarget, | 44 | lang_item::LangItemTarget, |
@@ -60,8 +56,8 @@ use hir_ty::{ | |||
60 | autoderef, | 56 | autoderef, |
61 | consteval::ConstExt, | 57 | consteval::ConstExt, |
62 | could_unify, | 58 | could_unify, |
63 | diagnostics_sink::DiagnosticSink, | 59 | diagnostics::BodyValidationDiagnostic, |
64 | method_resolution::{self, def_crates, TyFingerprint}, | 60 | method_resolution::{self, TyFingerprint}, |
65 | primitive::UintTy, | 61 | primitive::UintTy, |
66 | subst_prefix, | 62 | subst_prefix, |
67 | traits::FnTrait, | 63 | traits::FnTrait, |
@@ -72,6 +68,7 @@ use hir_ty::{ | |||
72 | }; | 68 | }; |
73 | use itertools::Itertools; | 69 | use itertools::Itertools; |
74 | use nameres::diagnostics::DefDiagnosticKind; | 70 | use nameres::diagnostics::DefDiagnosticKind; |
71 | use once_cell::unsync::Lazy; | ||
75 | use rustc_hash::FxHashSet; | 72 | use rustc_hash::FxHashSet; |
76 | use stdx::{format_to, impl_from}; | 73 | use stdx::{format_to, impl_from}; |
77 | use syntax::{ | 74 | use syntax::{ |
@@ -84,6 +81,13 @@ use crate::db::{DefDatabase, HirDatabase}; | |||
84 | 81 | ||
85 | pub use crate::{ | 82 | pub use crate::{ |
86 | attrs::{HasAttrs, Namespace}, | 83 | attrs::{HasAttrs, Namespace}, |
84 | diagnostics::{ | ||
85 | AnyDiagnostic, BreakOutsideOfLoop, InactiveCode, IncorrectCase, MacroError, | ||
86 | MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr, | ||
87 | MissingUnsafe, NoSuchField, RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap, | ||
88 | UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, | ||
89 | UnresolvedModule, UnresolvedProcMacro, | ||
90 | }, | ||
87 | has_source::HasSource, | 91 | has_source::HasSource, |
88 | semantics::{PathResolution, Semantics, SemanticsScope}, | 92 | semantics::{PathResolution, Semantics, SemanticsScope}, |
89 | }; | 93 | }; |
@@ -332,7 +336,7 @@ impl ModuleDef { | |||
332 | } | 336 | } |
333 | } | 337 | } |
334 | 338 | ||
335 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | 339 | pub fn diagnostics(self, db: &dyn HirDatabase) -> Vec<AnyDiagnostic> { |
336 | let id = match self { | 340 | let id = match self { |
337 | ModuleDef::Adt(it) => match it { | 341 | ModuleDef::Adt(it) => match it { |
338 | Adt::Struct(it) => it.id.into(), | 342 | Adt::Struct(it) => it.id.into(), |
@@ -345,15 +349,19 @@ impl ModuleDef { | |||
345 | ModuleDef::Module(it) => it.id.into(), | 349 | ModuleDef::Module(it) => it.id.into(), |
346 | ModuleDef::Const(it) => it.id.into(), | 350 | ModuleDef::Const(it) => it.id.into(), |
347 | ModuleDef::Static(it) => it.id.into(), | 351 | ModuleDef::Static(it) => it.id.into(), |
348 | _ => return, | 352 | _ => return Vec::new(), |
349 | }; | 353 | }; |
350 | 354 | ||
351 | let module = match self.module(db) { | 355 | let module = match self.module(db) { |
352 | Some(it) => it, | 356 | Some(it) => it, |
353 | None => return, | 357 | None => return Vec::new(), |
354 | }; | 358 | }; |
355 | 359 | ||
356 | hir_ty::diagnostics::validate_module_item(db, module.id.krate(), id, sink) | 360 | let mut acc = Vec::new(); |
361 | for diag in hir_ty::diagnostics::validate_module_item(db, module.id.krate(), id) { | ||
362 | acc.push(diag.into()) | ||
363 | } | ||
364 | acc | ||
357 | } | 365 | } |
358 | } | 366 | } |
359 | 367 | ||
@@ -442,10 +450,10 @@ impl Module { | |||
442 | } | 450 | } |
443 | 451 | ||
444 | pub fn visibility_of(self, db: &dyn HirDatabase, def: &ModuleDef) -> Option<Visibility> { | 452 | pub fn visibility_of(self, db: &dyn HirDatabase, def: &ModuleDef) -> Option<Visibility> { |
445 | self.id.def_map(db.upcast())[self.id.local_id].scope.visibility_of(def.clone().into()) | 453 | self.id.def_map(db.upcast())[self.id.local_id].scope.visibility_of((*def).into()) |
446 | } | 454 | } |
447 | 455 | ||
448 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | 456 | pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) { |
449 | let _p = profile::span("Module::diagnostics").detail(|| { | 457 | let _p = profile::span("Module::diagnostics").detail(|| { |
450 | format!("{:?}", self.name(db).map_or("<unknown>".into(), |name| name.to_string())) | 458 | format!("{:?}", self.name(db).map_or("<unknown>".into(), |name| name.to_string())) |
451 | }); | 459 | }); |
@@ -458,18 +466,22 @@ impl Module { | |||
458 | match &diag.kind { | 466 | match &diag.kind { |
459 | DefDiagnosticKind::UnresolvedModule { ast: declaration, candidate } => { | 467 | DefDiagnosticKind::UnresolvedModule { ast: declaration, candidate } => { |
460 | let decl = declaration.to_node(db.upcast()); | 468 | let decl = declaration.to_node(db.upcast()); |
461 | sink.push(UnresolvedModule { | 469 | acc.push( |
462 | file: declaration.file_id, | 470 | UnresolvedModule { |
463 | decl: AstPtr::new(&decl), | 471 | decl: InFile::new(declaration.file_id, AstPtr::new(&decl)), |
464 | candidate: candidate.clone(), | 472 | candidate: candidate.clone(), |
465 | }) | 473 | } |
474 | .into(), | ||
475 | ) | ||
466 | } | 476 | } |
467 | DefDiagnosticKind::UnresolvedExternCrate { ast } => { | 477 | DefDiagnosticKind::UnresolvedExternCrate { ast } => { |
468 | let item = ast.to_node(db.upcast()); | 478 | let item = ast.to_node(db.upcast()); |
469 | sink.push(UnresolvedExternCrate { | 479 | acc.push( |
470 | file: ast.file_id, | 480 | UnresolvedExternCrate { |
471 | item: AstPtr::new(&item), | 481 | decl: InFile::new(ast.file_id, AstPtr::new(&item)), |
472 | }); | 482 | } |
483 | .into(), | ||
484 | ); | ||
473 | } | 485 | } |
474 | 486 | ||
475 | DefDiagnosticKind::UnresolvedImport { id, index } => { | 487 | DefDiagnosticKind::UnresolvedImport { id, index } => { |
@@ -478,25 +490,30 @@ impl Module { | |||
478 | let import = &item_tree[id.value]; | 490 | let import = &item_tree[id.value]; |
479 | 491 | ||
480 | let use_tree = import.use_tree_to_ast(db.upcast(), file_id, *index); | 492 | 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) }); | 493 | acc.push( |
494 | UnresolvedImport { decl: InFile::new(file_id, AstPtr::new(&use_tree)) } | ||
495 | .into(), | ||
496 | ); | ||
482 | } | 497 | } |
483 | 498 | ||
484 | DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => { | 499 | DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => { |
485 | let item = ast.to_node(db.upcast()); | 500 | let item = ast.to_node(db.upcast()); |
486 | sink.push(InactiveCode { | 501 | acc.push( |
487 | file: ast.file_id, | 502 | InactiveCode { |
488 | node: AstPtr::new(&item).into(), | 503 | node: ast.with_value(AstPtr::new(&item).into()), |
489 | cfg: cfg.clone(), | 504 | cfg: cfg.clone(), |
490 | opts: opts.clone(), | 505 | opts: opts.clone(), |
491 | }); | 506 | } |
507 | .into(), | ||
508 | ); | ||
492 | } | 509 | } |
493 | 510 | ||
494 | DefDiagnosticKind::UnresolvedProcMacro { ast } => { | 511 | DefDiagnosticKind::UnresolvedProcMacro { ast } => { |
495 | let mut precise_location = None; | 512 | let mut precise_location = None; |
496 | let (file, ast, name) = match ast { | 513 | let (node, name) = match ast { |
497 | MacroCallKind::FnLike { ast_id, .. } => { | 514 | MacroCallKind::FnLike { ast_id, .. } => { |
498 | let node = ast_id.to_node(db.upcast()); | 515 | let node = ast_id.to_node(db.upcast()); |
499 | (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None) | 516 | (ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))), None) |
500 | } | 517 | } |
501 | MacroCallKind::Derive { ast_id, derive_name, .. } => { | 518 | MacroCallKind::Derive { ast_id, derive_name, .. } => { |
502 | let node = ast_id.to_node(db.upcast()); | 519 | let node = ast_id.to_node(db.upcast()); |
@@ -529,8 +546,7 @@ impl Module { | |||
529 | } | 546 | } |
530 | 547 | ||
531 | ( | 548 | ( |
532 | ast_id.file_id, | 549 | ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))), |
533 | SyntaxNodePtr::from(AstPtr::new(&node)), | ||
534 | Some(derive_name.clone()), | 550 | Some(derive_name.clone()), |
535 | ) | 551 | ) |
536 | } | 552 | } |
@@ -541,73 +557,73 @@ impl Module { | |||
541 | || panic!("cannot find attribute #{}", invoc_attr_index), | 557 | || panic!("cannot find attribute #{}", invoc_attr_index), |
542 | ); | 558 | ); |
543 | ( | 559 | ( |
544 | ast_id.file_id, | 560 | ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))), |
545 | SyntaxNodePtr::from(AstPtr::new(&attr)), | ||
546 | Some(attr_name.clone()), | 561 | Some(attr_name.clone()), |
547 | ) | 562 | ) |
548 | } | 563 | } |
549 | }; | 564 | }; |
550 | sink.push(UnresolvedProcMacro { | 565 | acc.push( |
551 | file, | 566 | UnresolvedProcMacro { node, precise_location, macro_name: name }.into(), |
552 | node: ast, | 567 | ); |
553 | precise_location, | ||
554 | macro_name: name, | ||
555 | }); | ||
556 | } | 568 | } |
557 | 569 | ||
558 | DefDiagnosticKind::UnresolvedMacroCall { ast, path } => { | 570 | DefDiagnosticKind::UnresolvedMacroCall { ast, path } => { |
559 | let node = ast.to_node(db.upcast()); | 571 | let node = ast.to_node(db.upcast()); |
560 | sink.push(UnresolvedMacroCall { | 572 | acc.push( |
561 | file: ast.file_id, | 573 | UnresolvedMacroCall { |
562 | node: AstPtr::new(&node), | 574 | macro_call: InFile::new(ast.file_id, AstPtr::new(&node)), |
563 | path: path.clone(), | 575 | path: path.clone(), |
564 | }); | 576 | } |
577 | .into(), | ||
578 | ); | ||
565 | } | 579 | } |
566 | 580 | ||
567 | DefDiagnosticKind::MacroError { ast, message } => { | 581 | DefDiagnosticKind::MacroError { ast, message } => { |
568 | let (file, ast) = match ast { | 582 | let node = match ast { |
569 | MacroCallKind::FnLike { ast_id, .. } => { | 583 | MacroCallKind::FnLike { ast_id, .. } => { |
570 | let node = ast_id.to_node(db.upcast()); | 584 | let node = ast_id.to_node(db.upcast()); |
571 | (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node))) | 585 | ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))) |
572 | } | 586 | } |
573 | MacroCallKind::Derive { ast_id, .. } | 587 | MacroCallKind::Derive { ast_id, .. } |
574 | | MacroCallKind::Attr { ast_id, .. } => { | 588 | | MacroCallKind::Attr { ast_id, .. } => { |
575 | // FIXME: point to the attribute instead, this creates very large diagnostics | 589 | // FIXME: point to the attribute instead, this creates very large diagnostics |
576 | let node = ast_id.to_node(db.upcast()); | 590 | let node = ast_id.to_node(db.upcast()); |
577 | (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node))) | 591 | ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))) |
578 | } | 592 | } |
579 | }; | 593 | }; |
580 | sink.push(MacroError { file, node: ast, message: message.clone() }); | 594 | acc.push(MacroError { node, message: message.clone() }.into()); |
581 | } | 595 | } |
582 | 596 | ||
583 | DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => { | 597 | DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => { |
584 | let node = ast.to_node(db.upcast()); | 598 | let node = ast.to_node(db.upcast()); |
585 | // Must have a name, otherwise we wouldn't emit it. | 599 | // Must have a name, otherwise we wouldn't emit it. |
586 | let name = node.name().expect("unimplemented builtin macro with no name"); | 600 | let name = node.name().expect("unimplemented builtin macro with no name"); |
587 | let ptr = SyntaxNodePtr::from(AstPtr::new(&name)); | 601 | acc.push( |
588 | sink.push(UnimplementedBuiltinMacro { file: ast.file_id, node: ptr }); | 602 | UnimplementedBuiltinMacro { |
603 | node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&name))), | ||
604 | } | ||
605 | .into(), | ||
606 | ); | ||
589 | } | 607 | } |
590 | } | 608 | } |
591 | } | 609 | } |
592 | for decl in self.declarations(db) { | 610 | for decl in self.declarations(db) { |
593 | match decl { | 611 | match decl { |
594 | crate::ModuleDef::Function(f) => f.diagnostics(db, sink), | 612 | ModuleDef::Function(f) => f.diagnostics(db, acc), |
595 | crate::ModuleDef::Module(m) => { | 613 | ModuleDef::Module(m) => { |
596 | // Only add diagnostics from inline modules | 614 | // Only add diagnostics from inline modules |
597 | if def_map[m.id.local_id].origin.is_inline() { | 615 | if def_map[m.id.local_id].origin.is_inline() { |
598 | m.diagnostics(db, sink) | 616 | m.diagnostics(db, acc) |
599 | } | 617 | } |
600 | } | 618 | } |
601 | _ => { | 619 | _ => acc.extend(decl.diagnostics(db)), |
602 | decl.diagnostics(db, sink); | ||
603 | } | ||
604 | } | 620 | } |
605 | } | 621 | } |
606 | 622 | ||
607 | for impl_def in self.impl_defs(db) { | 623 | for impl_def in self.impl_defs(db) { |
608 | for item in impl_def.items(db) { | 624 | for item in impl_def.items(db) { |
609 | if let AssocItem::Function(f) = item { | 625 | if let AssocItem::Function(f) = item { |
610 | f.diagnostics(db, sink); | 626 | f.diagnostics(db, acc); |
611 | } | 627 | } |
612 | } | 628 | } |
613 | } | 629 | } |
@@ -1009,41 +1025,191 @@ impl Function { | |||
1009 | db.function_data(self.id).is_async() | 1025 | db.function_data(self.id).is_async() |
1010 | } | 1026 | } |
1011 | 1027 | ||
1012 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | 1028 | pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) { |
1013 | let krate = self.module(db).id.krate(); | 1029 | let krate = self.module(db).id.krate(); |
1014 | 1030 | ||
1015 | let source_map = db.body_with_source_map(self.id.into()).1; | 1031 | let source_map = db.body_with_source_map(self.id.into()).1; |
1016 | for diag in source_map.diagnostics() { | 1032 | for diag in source_map.diagnostics() { |
1017 | match diag { | 1033 | match diag { |
1018 | BodyDiagnostic::InactiveCode { node, cfg, opts } => sink.push(InactiveCode { | 1034 | BodyDiagnostic::InactiveCode { node, cfg, opts } => acc.push( |
1019 | file: node.file_id, | 1035 | InactiveCode { node: node.clone(), cfg: cfg.clone(), opts: opts.clone() } |
1020 | node: node.value.clone(), | 1036 | .into(), |
1021 | cfg: cfg.clone(), | 1037 | ), |
1022 | opts: opts.clone(), | 1038 | BodyDiagnostic::MacroError { node, message } => acc.push( |
1023 | }), | 1039 | MacroError { |
1024 | BodyDiagnostic::MacroError { node, message } => sink.push(MacroError { | 1040 | node: node.clone().map(|it| it.into()), |
1025 | file: node.file_id, | 1041 | message: message.to_string(), |
1026 | node: node.value.clone().into(), | 1042 | } |
1027 | message: message.to_string(), | 1043 | .into(), |
1028 | }), | 1044 | ), |
1029 | BodyDiagnostic::UnresolvedProcMacro { node } => sink.push(UnresolvedProcMacro { | 1045 | BodyDiagnostic::UnresolvedProcMacro { node } => acc.push( |
1030 | file: node.file_id, | 1046 | UnresolvedProcMacro { |
1031 | node: node.value.clone().into(), | 1047 | node: node.clone().map(|it| it.into()), |
1032 | precise_location: None, | 1048 | precise_location: None, |
1033 | macro_name: None, | 1049 | macro_name: None, |
1034 | }), | 1050 | } |
1035 | BodyDiagnostic::UnresolvedMacroCall { node, path } => { | 1051 | .into(), |
1036 | sink.push(UnresolvedMacroCall { | 1052 | ), |
1037 | file: node.file_id, | 1053 | BodyDiagnostic::UnresolvedMacroCall { node, path } => acc.push( |
1038 | node: node.value.clone(), | 1054 | UnresolvedMacroCall { macro_call: node.clone(), path: path.clone() }.into(), |
1039 | path: path.clone(), | 1055 | ), |
1040 | }) | 1056 | } |
1057 | } | ||
1058 | |||
1059 | let infer = db.infer(self.id.into()); | ||
1060 | let source_map = Lazy::new(|| db.body_with_source_map(self.id.into()).1); | ||
1061 | for d in &infer.diagnostics { | ||
1062 | match d { | ||
1063 | hir_ty::InferenceDiagnostic::NoSuchField { expr } => { | ||
1064 | let field = source_map.field_syntax(*expr); | ||
1065 | acc.push(NoSuchField { field }.into()) | ||
1066 | } | ||
1067 | hir_ty::InferenceDiagnostic::BreakOutsideOfLoop { expr } => { | ||
1068 | let expr = source_map | ||
1069 | .expr_syntax(*expr) | ||
1070 | .expect("break outside of loop in synthetic syntax"); | ||
1071 | acc.push(BreakOutsideOfLoop { expr }.into()) | ||
1041 | } | 1072 | } |
1042 | } | 1073 | } |
1043 | } | 1074 | } |
1044 | 1075 | ||
1045 | hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink); | 1076 | for expr in hir_ty::diagnostics::missing_unsafe(db, self.id.into()) { |
1046 | hir_ty::diagnostics::validate_body(db, self.id.into(), sink); | 1077 | match source_map.expr_syntax(expr) { |
1078 | Ok(expr) => acc.push(MissingUnsafe { expr }.into()), | ||
1079 | Err(SyntheticSyntax) => { | ||
1080 | // FIXME: Here and eslwhere in this file, the `expr` was | ||
1081 | // desugared, report or assert that this doesn't happen. | ||
1082 | } | ||
1083 | } | ||
1084 | } | ||
1085 | |||
1086 | for diagnostic in BodyValidationDiagnostic::collect(db, self.id.into()) { | ||
1087 | match diagnostic { | ||
1088 | BodyValidationDiagnostic::RecordMissingFields { | ||
1089 | record, | ||
1090 | variant, | ||
1091 | missed_fields, | ||
1092 | } => { | ||
1093 | let variant_data = variant.variant_data(db.upcast()); | ||
1094 | let missed_fields = missed_fields | ||
1095 | .into_iter() | ||
1096 | .map(|idx| variant_data.fields()[idx].name.clone()) | ||
1097 | .collect(); | ||
1098 | |||
1099 | match record { | ||
1100 | Either::Left(record_expr) => match source_map.expr_syntax(record_expr) { | ||
1101 | Ok(source_ptr) => { | ||
1102 | let root = source_ptr.file_syntax(db.upcast()); | ||
1103 | if let ast::Expr::RecordExpr(record_expr) = | ||
1104 | &source_ptr.value.to_node(&root) | ||
1105 | { | ||
1106 | if let Some(_) = record_expr.record_expr_field_list() { | ||
1107 | acc.push( | ||
1108 | MissingFields { | ||
1109 | file: source_ptr.file_id, | ||
1110 | field_list_parent: Either::Left(AstPtr::new( | ||
1111 | record_expr, | ||
1112 | )), | ||
1113 | field_list_parent_path: record_expr | ||
1114 | .path() | ||
1115 | .map(|path| AstPtr::new(&path)), | ||
1116 | missed_fields, | ||
1117 | } | ||
1118 | .into(), | ||
1119 | ) | ||
1120 | } | ||
1121 | } | ||
1122 | } | ||
1123 | Err(SyntheticSyntax) => (), | ||
1124 | }, | ||
1125 | Either::Right(record_pat) => match source_map.pat_syntax(record_pat) { | ||
1126 | Ok(source_ptr) => { | ||
1127 | if let Some(expr) = source_ptr.value.as_ref().left() { | ||
1128 | let root = source_ptr.file_syntax(db.upcast()); | ||
1129 | if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) { | ||
1130 | if let Some(_) = record_pat.record_pat_field_list() { | ||
1131 | acc.push( | ||
1132 | MissingFields { | ||
1133 | file: source_ptr.file_id, | ||
1134 | field_list_parent: Either::Right(AstPtr::new( | ||
1135 | &record_pat, | ||
1136 | )), | ||
1137 | field_list_parent_path: record_pat | ||
1138 | .path() | ||
1139 | .map(|path| AstPtr::new(&path)), | ||
1140 | missed_fields, | ||
1141 | } | ||
1142 | .into(), | ||
1143 | ) | ||
1144 | } | ||
1145 | } | ||
1146 | } | ||
1147 | } | ||
1148 | Err(SyntheticSyntax) => (), | ||
1149 | }, | ||
1150 | } | ||
1151 | } | ||
1152 | BodyValidationDiagnostic::ReplaceFilterMapNextWithFindMap { method_call_expr } => { | ||
1153 | if let Ok(next_source_ptr) = source_map.expr_syntax(method_call_expr) { | ||
1154 | acc.push( | ||
1155 | ReplaceFilterMapNextWithFindMap { | ||
1156 | file: next_source_ptr.file_id, | ||
1157 | next_expr: next_source_ptr.value, | ||
1158 | } | ||
1159 | .into(), | ||
1160 | ); | ||
1161 | } | ||
1162 | } | ||
1163 | BodyValidationDiagnostic::MismatchedArgCount { call_expr, expected, found } => { | ||
1164 | match source_map.expr_syntax(call_expr) { | ||
1165 | Ok(source_ptr) => acc.push( | ||
1166 | MismatchedArgCount { call_expr: source_ptr, expected, found }.into(), | ||
1167 | ), | ||
1168 | Err(SyntheticSyntax) => (), | ||
1169 | } | ||
1170 | } | ||
1171 | BodyValidationDiagnostic::RemoveThisSemicolon { expr } => { | ||
1172 | match source_map.expr_syntax(expr) { | ||
1173 | Ok(expr) => acc.push(RemoveThisSemicolon { expr }.into()), | ||
1174 | Err(SyntheticSyntax) => (), | ||
1175 | } | ||
1176 | } | ||
1177 | BodyValidationDiagnostic::MissingOkOrSomeInTailExpr { expr, required } => { | ||
1178 | match source_map.expr_syntax(expr) { | ||
1179 | Ok(expr) => acc.push(MissingOkOrSomeInTailExpr { expr, required }.into()), | ||
1180 | Err(SyntheticSyntax) => (), | ||
1181 | } | ||
1182 | } | ||
1183 | BodyValidationDiagnostic::MissingMatchArms { match_expr } => { | ||
1184 | match source_map.expr_syntax(match_expr) { | ||
1185 | Ok(source_ptr) => { | ||
1186 | let root = source_ptr.file_syntax(db.upcast()); | ||
1187 | if let ast::Expr::MatchExpr(match_expr) = | ||
1188 | &source_ptr.value.to_node(&root) | ||
1189 | { | ||
1190 | if let (Some(match_expr), Some(arms)) = | ||
1191 | (match_expr.expr(), match_expr.match_arm_list()) | ||
1192 | { | ||
1193 | acc.push( | ||
1194 | MissingMatchArms { | ||
1195 | file: source_ptr.file_id, | ||
1196 | match_expr: AstPtr::new(&match_expr), | ||
1197 | arms: AstPtr::new(&arms), | ||
1198 | } | ||
1199 | .into(), | ||
1200 | ) | ||
1201 | } | ||
1202 | } | ||
1203 | } | ||
1204 | Err(SyntheticSyntax) => (), | ||
1205 | } | ||
1206 | } | ||
1207 | } | ||
1208 | } | ||
1209 | |||
1210 | for diag in hir_ty::diagnostics::validate_module_item(db, krate, self.id.into()) { | ||
1211 | acc.push(diag.into()) | ||
1212 | } | ||
1047 | } | 1213 | } |
1048 | 1214 | ||
1049 | /// Whether this function declaration has a definition. | 1215 | /// Whether this function declaration has a definition. |
@@ -1762,7 +1928,7 @@ impl Impl { | |||
1762 | } | 1928 | } |
1763 | 1929 | ||
1764 | pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<Impl> { | 1930 | pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<Impl> { |
1765 | let def_crates = match def_crates(db, &ty, krate) { | 1931 | let def_crates = match method_resolution::def_crates(db, &ty, krate) { |
1766 | Some(def_crates) => def_crates, | 1932 | Some(def_crates) => def_crates, |
1767 | None => return Vec::new(), | 1933 | None => return Vec::new(), |
1768 | }; | 1934 | }; |
@@ -2168,7 +2334,7 @@ impl Type { | |||
2168 | krate: Crate, | 2334 | krate: Crate, |
2169 | mut callback: impl FnMut(AssocItem) -> Option<T>, | 2335 | mut callback: impl FnMut(AssocItem) -> Option<T>, |
2170 | ) -> Option<T> { | 2336 | ) -> Option<T> { |
2171 | for krate in def_crates(db, &self.ty, krate.id)? { | 2337 | for krate in method_resolution::def_crates(db, &self.ty, krate.id)? { |
2172 | let impls = db.inherent_impls_in_crate(krate); | 2338 | let impls = db.inherent_impls_in_crate(krate); |
2173 | 2339 | ||
2174 | for impl_def in impls.for_self_ty(&self.ty) { | 2340 | for impl_def in impls.for_self_ty(&self.ty) { |
@@ -2345,13 +2511,13 @@ impl Type { | |||
2345 | match ty.kind(&Interner) { | 2511 | match ty.kind(&Interner) { |
2346 | TyKind::Adt(_, substs) => { | 2512 | TyKind::Adt(_, substs) => { |
2347 | cb(type_.derived(ty.clone())); | 2513 | cb(type_.derived(ty.clone())); |
2348 | walk_substs(db, type_, &substs, cb); | 2514 | walk_substs(db, type_, substs, cb); |
2349 | } | 2515 | } |
2350 | TyKind::AssociatedType(_, substs) => { | 2516 | TyKind::AssociatedType(_, substs) => { |
2351 | if let Some(_) = ty.associated_type_parent_trait(db) { | 2517 | if let Some(_) = ty.associated_type_parent_trait(db) { |
2352 | cb(type_.derived(ty.clone())); | 2518 | cb(type_.derived(ty.clone())); |
2353 | } | 2519 | } |
2354 | walk_substs(db, type_, &substs, cb); | 2520 | walk_substs(db, type_, substs, cb); |
2355 | } | 2521 | } |
2356 | TyKind::OpaqueType(_, subst) => { | 2522 | TyKind::OpaqueType(_, subst) => { |
2357 | if let Some(bounds) = ty.impl_trait_bounds(db) { | 2523 | if let Some(bounds) = ty.impl_trait_bounds(db) { |
@@ -2391,7 +2557,7 @@ impl Type { | |||
2391 | TyKind::FnDef(_, substs) | 2557 | TyKind::FnDef(_, substs) |
2392 | | TyKind::Tuple(_, substs) | 2558 | | TyKind::Tuple(_, substs) |
2393 | | TyKind::Closure(.., substs) => { | 2559 | | TyKind::Closure(.., substs) => { |
2394 | walk_substs(db, type_, &substs, cb); | 2560 | walk_substs(db, type_, substs, cb); |
2395 | } | 2561 | } |
2396 | TyKind::Function(hir_ty::FnPointer { substitution, .. }) => { | 2562 | TyKind::Function(hir_ty::FnPointer { substitution, .. }) => { |
2397 | walk_substs(db, type_, &substitution.0, cb); | 2563 | walk_substs(db, type_, &substitution.0, cb); |
@@ -2522,18 +2688,6 @@ impl ScopeDef { | |||
2522 | 2688 | ||
2523 | items | 2689 | items |
2524 | } | 2690 | } |
2525 | |||
2526 | pub fn is_value_def(&self) -> bool { | ||
2527 | matches!( | ||
2528 | self, | ||
2529 | ScopeDef::ModuleDef(ModuleDef::Function(_)) | ||
2530 | | ScopeDef::ModuleDef(ModuleDef::Variant(_)) | ||
2531 | | ScopeDef::ModuleDef(ModuleDef::Const(_)) | ||
2532 | | ScopeDef::ModuleDef(ModuleDef::Static(_)) | ||
2533 | | ScopeDef::GenericParam(GenericParam::ConstParam(_)) | ||
2534 | | ScopeDef::Local(_) | ||
2535 | ) | ||
2536 | } | ||
2537 | } | 2691 | } |
2538 | 2692 | ||
2539 | impl From<ItemInNs> for ScopeDef { | 2693 | impl From<ItemInNs> for ScopeDef { |