diff options
Diffstat (limited to 'crates/hir/src')
-rw-r--r-- | crates/hir/src/diagnostics.rs | 297 | ||||
-rw-r--r-- | crates/hir/src/lib.rs | 364 | ||||
-rw-r--r-- | crates/hir/src/semantics.rs | 4 | ||||
-rw-r--r-- | crates/hir/src/source_analyzer.rs | 6 |
4 files changed, 378 insertions, 293 deletions
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index 2cdbd172a..b4c505898 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs | |||
@@ -3,251 +3,152 @@ | |||
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. |
6 | use std::any::Any; | 6 | use cfg::{CfgExpr, CfgOptions}; |
7 | 7 | use either::Either; | |
8 | use cfg::{CfgExpr, CfgOptions, DnfExpr}; | ||
9 | use hir_def::path::ModPath; | 8 | use hir_def::path::ModPath; |
10 | use hir_expand::{HirFileId, InFile}; | 9 | use hir_expand::{name::Name, HirFileId, InFile}; |
11 | use stdx::format_to; | ||
12 | use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange}; | 10 | use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange}; |
13 | 11 | ||
14 | pub use hir_ty::{ | 12 | macro_rules! diagnostics { |
15 | diagnostics::{ | 13 | ($($diag:ident,)*) => { |
16 | IncorrectCase, MismatchedArgCount, MissingFields, MissingMatchArms, | 14 | pub enum AnyDiagnostic {$( |
17 | MissingOkOrSomeInTailExpr, NoSuchField, RemoveThisSemicolon, | 15 | $diag(Box<$diag>), |
18 | ReplaceFilterMapNextWithFindMap, | 16 | )*} |
19 | }, | 17 | |
20 | diagnostics_sink::{Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder}, | 18 | $( |
21 | }; | 19 | impl From<$diag> for AnyDiagnostic { |
22 | 20 | fn from(d: $diag) -> AnyDiagnostic { | |
23 | // Diagnostic: unresolved-module | 21 | AnyDiagnostic::$diag(Box::new(d)) |
24 | // | 22 | } |
25 | // This diagnostic is triggered if rust-analyzer is unable to discover referred module. | 23 | } |
24 | )* | ||
25 | }; | ||
26 | } | ||
27 | |||
28 | diagnostics![ | ||
29 | BreakOutsideOfLoop, | ||
30 | InactiveCode, | ||
31 | IncorrectCase, | ||
32 | MacroError, | ||
33 | MismatchedArgCount, | ||
34 | MissingFields, | ||
35 | MissingMatchArms, | ||
36 | MissingOkOrSomeInTailExpr, | ||
37 | MissingUnsafe, | ||
38 | NoSuchField, | ||
39 | RemoveThisSemicolon, | ||
40 | ReplaceFilterMapNextWithFindMap, | ||
41 | UnimplementedBuiltinMacro, | ||
42 | UnresolvedExternCrate, | ||
43 | UnresolvedImport, | ||
44 | UnresolvedMacroCall, | ||
45 | UnresolvedModule, | ||
46 | UnresolvedProcMacro, | ||
47 | ]; | ||
48 | |||
26 | #[derive(Debug)] | 49 | #[derive(Debug)] |
27 | pub struct UnresolvedModule { | 50 | pub struct UnresolvedModule { |
28 | pub file: HirFileId, | 51 | pub decl: InFile<AstPtr<ast::Module>>, |
29 | pub decl: AstPtr<ast::Module>, | ||
30 | pub candidate: String, | 52 | pub candidate: String, |
31 | } | 53 | } |
32 | 54 | ||
33 | impl 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)] | 55 | #[derive(Debug)] |
52 | pub struct UnresolvedExternCrate { | 56 | pub struct UnresolvedExternCrate { |
53 | pub file: HirFileId, | 57 | pub decl: InFile<AstPtr<ast::ExternCrate>>, |
54 | pub item: AstPtr<ast::ExternCrate>, | ||
55 | } | ||
56 | |||
57 | impl 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 | } | 58 | } |
71 | 59 | ||
72 | #[derive(Debug)] | 60 | #[derive(Debug)] |
73 | pub struct UnresolvedImport { | 61 | pub struct UnresolvedImport { |
74 | pub file: HirFileId, | 62 | pub decl: InFile<AstPtr<ast::UseTree>>, |
75 | pub node: AstPtr<ast::UseTree>, | 63 | } |
76 | } | 64 | |
77 | |||
78 | impl 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)] | 65 | #[derive(Debug, Clone, Eq, PartialEq)] |
105 | pub struct UnresolvedMacroCall { | 66 | pub struct UnresolvedMacroCall { |
106 | pub file: HirFileId, | 67 | pub macro_call: InFile<AstPtr<ast::MacroCall>>, |
107 | pub node: AstPtr<ast::MacroCall>, | ||
108 | pub path: ModPath, | 68 | pub path: ModPath, |
109 | } | 69 | } |
110 | 70 | ||
111 | impl 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)] | 71 | #[derive(Debug, Clone, Eq, PartialEq)] |
133 | pub struct InactiveCode { | 72 | pub struct InactiveCode { |
134 | pub file: HirFileId, | 73 | pub node: InFile<SyntaxNodePtr>, |
135 | pub node: SyntaxNodePtr, | ||
136 | pub cfg: CfgExpr, | 74 | pub cfg: CfgExpr, |
137 | pub opts: CfgOptions, | 75 | pub opts: CfgOptions, |
138 | } | 76 | } |
139 | 77 | ||
140 | impl 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)] | 78 | #[derive(Debug, Clone, Eq, PartialEq)] |
172 | pub struct UnresolvedProcMacro { | 79 | pub struct UnresolvedProcMacro { |
173 | pub file: HirFileId, | 80 | pub node: InFile<SyntaxNodePtr>, |
174 | pub node: SyntaxNodePtr, | ||
175 | /// If the diagnostic can be pinpointed more accurately than via `node`, this is the `TextRange` | 81 | /// If the diagnostic can be pinpointed more accurately than via `node`, this is the `TextRange` |
176 | /// to use instead. | 82 | /// to use instead. |
177 | pub precise_location: Option<TextRange>, | 83 | pub precise_location: Option<TextRange>, |
178 | pub macro_name: Option<String>, | 84 | pub macro_name: Option<String>, |
179 | } | 85 | } |
180 | 86 | ||
181 | impl Diagnostic for UnresolvedProcMacro { | 87 | #[derive(Debug, Clone, Eq, PartialEq)] |
182 | fn code(&self) -> DiagnosticCode { | 88 | pub struct MacroError { |
183 | DiagnosticCode("unresolved-proc-macro") | 89 | pub node: InFile<SyntaxNodePtr>, |
184 | } | 90 | pub message: String, |
91 | } | ||
185 | 92 | ||
186 | fn message(&self) -> String { | 93 | #[derive(Debug)] |
187 | match &self.macro_name { | 94 | pub struct UnimplementedBuiltinMacro { |
188 | Some(name) => format!("proc macro `{}` not expanded", name), | 95 | pub node: InFile<SyntaxNodePtr>, |
189 | None => "proc macro not expanded".to_string(), | 96 | } |
190 | } | ||
191 | } | ||
192 | 97 | ||
193 | fn display_source(&self) -> InFile<SyntaxNodePtr> { | 98 | #[derive(Debug)] |
194 | InFile::new(self.file, self.node.clone()) | 99 | pub struct NoSuchField { |
195 | } | 100 | pub field: InFile<AstPtr<ast::RecordExprField>>, |
101 | } | ||
196 | 102 | ||
197 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 103 | #[derive(Debug)] |
198 | self | 104 | pub struct BreakOutsideOfLoop { |
199 | } | 105 | pub expr: InFile<AstPtr<ast::Expr>>, |
200 | } | 106 | } |
201 | 107 | ||
202 | // Diagnostic: macro-error | 108 | #[derive(Debug)] |
203 | // | 109 | pub struct MissingUnsafe { |
204 | // This diagnostic is shown for macro expansion errors. | 110 | pub expr: InFile<AstPtr<ast::Expr>>, |
205 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
206 | pub struct MacroError { | ||
207 | pub file: HirFileId, | ||
208 | pub node: SyntaxNodePtr, | ||
209 | pub message: String, | ||
210 | } | 111 | } |
211 | 112 | ||
212 | impl Diagnostic for MacroError { | 113 | #[derive(Debug)] |
213 | fn code(&self) -> DiagnosticCode { | 114 | pub struct MissingFields { |
214 | DiagnosticCode("macro-error") | 115 | pub file: HirFileId, |
215 | } | 116 | pub field_list_parent: Either<AstPtr<ast::RecordExpr>, AstPtr<ast::RecordPat>>, |
216 | fn message(&self) -> String { | 117 | pub field_list_parent_path: Option<AstPtr<ast::Path>>, |
217 | self.message.clone() | 118 | pub missed_fields: Vec<Name>, |
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 | } | 119 | } |
230 | 120 | ||
231 | #[derive(Debug)] | 121 | #[derive(Debug)] |
232 | pub struct UnimplementedBuiltinMacro { | 122 | pub struct ReplaceFilterMapNextWithFindMap { |
233 | pub file: HirFileId, | 123 | pub file: HirFileId, |
234 | pub node: SyntaxNodePtr, | 124 | /// This expression is the whole method chain up to and including `.filter_map(..).next()`. |
125 | pub next_expr: AstPtr<ast::Expr>, | ||
235 | } | 126 | } |
236 | 127 | ||
237 | impl Diagnostic for UnimplementedBuiltinMacro { | 128 | #[derive(Debug)] |
238 | fn code(&self) -> DiagnosticCode { | 129 | pub struct MismatchedArgCount { |
239 | DiagnosticCode("unimplemented-builtin-macro") | 130 | pub call_expr: InFile<AstPtr<ast::Expr>>, |
240 | } | 131 | pub expected: usize, |
132 | pub found: usize, | ||
133 | } | ||
241 | 134 | ||
242 | fn message(&self) -> String { | 135 | #[derive(Debug)] |
243 | "unimplemented built-in macro".to_string() | 136 | pub struct RemoveThisSemicolon { |
244 | } | 137 | pub expr: InFile<AstPtr<ast::Expr>>, |
138 | } | ||
245 | 139 | ||
246 | fn display_source(&self) -> InFile<SyntaxNodePtr> { | 140 | #[derive(Debug)] |
247 | InFile::new(self.file, self.node.clone()) | 141 | pub struct MissingOkOrSomeInTailExpr { |
248 | } | 142 | pub expr: InFile<AstPtr<ast::Expr>>, |
143 | // `Some` or `Ok` depending on whether the return type is Result or Option | ||
144 | pub required: String, | ||
145 | } | ||
249 | 146 | ||
250 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 147 | #[derive(Debug)] |
251 | self | 148 | pub struct MissingMatchArms { |
252 | } | 149 | pub file: HirFileId, |
150 | pub match_expr: AstPtr<ast::Expr>, | ||
151 | pub arms: AstPtr<ast::MatchArmList>, | ||
253 | } | 152 | } |
153 | |||
154 | pub use hir_ty::diagnostics::IncorrectCase; | ||
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 2ec568b26..5bc0b2338 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -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 | }; |
@@ -191,6 +195,7 @@ impl Crate { | |||
191 | db: &dyn DefDatabase, | 195 | db: &dyn DefDatabase, |
192 | query: import_map::Query, | 196 | query: import_map::Query, |
193 | ) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> { | 197 | ) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> { |
198 | let _p = profile::span("query_external_importables"); | ||
194 | import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| match item { | 199 | import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| match item { |
195 | ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id.into()), | 200 | ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id.into()), |
196 | ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()), | 201 | ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()), |
@@ -331,7 +336,7 @@ impl ModuleDef { | |||
331 | } | 336 | } |
332 | } | 337 | } |
333 | 338 | ||
334 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | 339 | pub fn diagnostics(self, db: &dyn HirDatabase) -> Vec<AnyDiagnostic> { |
335 | let id = match self { | 340 | let id = match self { |
336 | ModuleDef::Adt(it) => match it { | 341 | ModuleDef::Adt(it) => match it { |
337 | Adt::Struct(it) => it.id.into(), | 342 | Adt::Struct(it) => it.id.into(), |
@@ -344,15 +349,19 @@ impl ModuleDef { | |||
344 | ModuleDef::Module(it) => it.id.into(), | 349 | ModuleDef::Module(it) => it.id.into(), |
345 | ModuleDef::Const(it) => it.id.into(), | 350 | ModuleDef::Const(it) => it.id.into(), |
346 | ModuleDef::Static(it) => it.id.into(), | 351 | ModuleDef::Static(it) => it.id.into(), |
347 | _ => return, | 352 | _ => return Vec::new(), |
348 | }; | 353 | }; |
349 | 354 | ||
350 | let module = match self.module(db) { | 355 | let module = match self.module(db) { |
351 | Some(it) => it, | 356 | Some(it) => it, |
352 | None => return, | 357 | None => return Vec::new(), |
353 | }; | 358 | }; |
354 | 359 | ||
355 | 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 | ||
356 | } | 365 | } |
357 | } | 366 | } |
358 | 367 | ||
@@ -441,10 +450,10 @@ impl Module { | |||
441 | } | 450 | } |
442 | 451 | ||
443 | 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> { |
444 | 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()) |
445 | } | 454 | } |
446 | 455 | ||
447 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | 456 | pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) { |
448 | let _p = profile::span("Module::diagnostics").detail(|| { | 457 | let _p = profile::span("Module::diagnostics").detail(|| { |
449 | 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())) |
450 | }); | 459 | }); |
@@ -457,18 +466,22 @@ impl Module { | |||
457 | match &diag.kind { | 466 | match &diag.kind { |
458 | DefDiagnosticKind::UnresolvedModule { ast: declaration, candidate } => { | 467 | DefDiagnosticKind::UnresolvedModule { ast: declaration, candidate } => { |
459 | let decl = declaration.to_node(db.upcast()); | 468 | let decl = declaration.to_node(db.upcast()); |
460 | sink.push(UnresolvedModule { | 469 | acc.push( |
461 | file: declaration.file_id, | 470 | UnresolvedModule { |
462 | decl: AstPtr::new(&decl), | 471 | decl: InFile::new(declaration.file_id, AstPtr::new(&decl)), |
463 | candidate: candidate.clone(), | 472 | candidate: candidate.clone(), |
464 | }) | 473 | } |
474 | .into(), | ||
475 | ) | ||
465 | } | 476 | } |
466 | DefDiagnosticKind::UnresolvedExternCrate { ast } => { | 477 | DefDiagnosticKind::UnresolvedExternCrate { ast } => { |
467 | let item = ast.to_node(db.upcast()); | 478 | let item = ast.to_node(db.upcast()); |
468 | sink.push(UnresolvedExternCrate { | 479 | acc.push( |
469 | file: ast.file_id, | 480 | UnresolvedExternCrate { |
470 | item: AstPtr::new(&item), | 481 | decl: InFile::new(ast.file_id, AstPtr::new(&item)), |
471 | }); | 482 | } |
483 | .into(), | ||
484 | ); | ||
472 | } | 485 | } |
473 | 486 | ||
474 | DefDiagnosticKind::UnresolvedImport { id, index } => { | 487 | DefDiagnosticKind::UnresolvedImport { id, index } => { |
@@ -477,25 +490,30 @@ impl Module { | |||
477 | let import = &item_tree[id.value]; | 490 | let import = &item_tree[id.value]; |
478 | 491 | ||
479 | 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); |
480 | 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 | ); | ||
481 | } | 497 | } |
482 | 498 | ||
483 | DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => { | 499 | DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => { |
484 | let item = ast.to_node(db.upcast()); | 500 | let item = ast.to_node(db.upcast()); |
485 | sink.push(InactiveCode { | 501 | acc.push( |
486 | file: ast.file_id, | 502 | InactiveCode { |
487 | node: AstPtr::new(&item).into(), | 503 | node: ast.with_value(AstPtr::new(&item).into()), |
488 | cfg: cfg.clone(), | 504 | cfg: cfg.clone(), |
489 | opts: opts.clone(), | 505 | opts: opts.clone(), |
490 | }); | 506 | } |
507 | .into(), | ||
508 | ); | ||
491 | } | 509 | } |
492 | 510 | ||
493 | DefDiagnosticKind::UnresolvedProcMacro { ast } => { | 511 | DefDiagnosticKind::UnresolvedProcMacro { ast } => { |
494 | let mut precise_location = None; | 512 | let mut precise_location = None; |
495 | let (file, ast, name) = match ast { | 513 | let (node, name) = match ast { |
496 | MacroCallKind::FnLike { ast_id, .. } => { | 514 | MacroCallKind::FnLike { ast_id, .. } => { |
497 | let node = ast_id.to_node(db.upcast()); | 515 | let node = ast_id.to_node(db.upcast()); |
498 | (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None) | 516 | (ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))), None) |
499 | } | 517 | } |
500 | MacroCallKind::Derive { ast_id, derive_name, .. } => { | 518 | MacroCallKind::Derive { ast_id, derive_name, .. } => { |
501 | let node = ast_id.to_node(db.upcast()); | 519 | let node = ast_id.to_node(db.upcast()); |
@@ -528,8 +546,7 @@ impl Module { | |||
528 | } | 546 | } |
529 | 547 | ||
530 | ( | 548 | ( |
531 | ast_id.file_id, | 549 | ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))), |
532 | SyntaxNodePtr::from(AstPtr::new(&node)), | ||
533 | Some(derive_name.clone()), | 550 | Some(derive_name.clone()), |
534 | ) | 551 | ) |
535 | } | 552 | } |
@@ -540,73 +557,73 @@ impl Module { | |||
540 | || panic!("cannot find attribute #{}", invoc_attr_index), | 557 | || panic!("cannot find attribute #{}", invoc_attr_index), |
541 | ); | 558 | ); |
542 | ( | 559 | ( |
543 | ast_id.file_id, | 560 | ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))), |
544 | SyntaxNodePtr::from(AstPtr::new(&attr)), | ||
545 | Some(attr_name.clone()), | 561 | Some(attr_name.clone()), |
546 | ) | 562 | ) |
547 | } | 563 | } |
548 | }; | 564 | }; |
549 | sink.push(UnresolvedProcMacro { | 565 | acc.push( |
550 | file, | 566 | UnresolvedProcMacro { node, precise_location, macro_name: name }.into(), |
551 | node: ast, | 567 | ); |
552 | precise_location, | ||
553 | macro_name: name, | ||
554 | }); | ||
555 | } | 568 | } |
556 | 569 | ||
557 | DefDiagnosticKind::UnresolvedMacroCall { ast, path } => { | 570 | DefDiagnosticKind::UnresolvedMacroCall { ast, path } => { |
558 | let node = ast.to_node(db.upcast()); | 571 | let node = ast.to_node(db.upcast()); |
559 | sink.push(UnresolvedMacroCall { | 572 | acc.push( |
560 | file: ast.file_id, | 573 | UnresolvedMacroCall { |
561 | node: AstPtr::new(&node), | 574 | macro_call: InFile::new(ast.file_id, AstPtr::new(&node)), |
562 | path: path.clone(), | 575 | path: path.clone(), |
563 | }); | 576 | } |
577 | .into(), | ||
578 | ); | ||
564 | } | 579 | } |
565 | 580 | ||
566 | DefDiagnosticKind::MacroError { ast, message } => { | 581 | DefDiagnosticKind::MacroError { ast, message } => { |
567 | let (file, ast) = match ast { | 582 | let node = match ast { |
568 | MacroCallKind::FnLike { ast_id, .. } => { | 583 | MacroCallKind::FnLike { ast_id, .. } => { |
569 | let node = ast_id.to_node(db.upcast()); | 584 | let node = ast_id.to_node(db.upcast()); |
570 | (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node))) | 585 | ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))) |
571 | } | 586 | } |
572 | MacroCallKind::Derive { ast_id, .. } | 587 | MacroCallKind::Derive { ast_id, .. } |
573 | | MacroCallKind::Attr { ast_id, .. } => { | 588 | | MacroCallKind::Attr { ast_id, .. } => { |
574 | // FIXME: point to the attribute instead, this creates very large diagnostics | 589 | // FIXME: point to the attribute instead, this creates very large diagnostics |
575 | let node = ast_id.to_node(db.upcast()); | 590 | let node = ast_id.to_node(db.upcast()); |
576 | (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node))) | 591 | ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))) |
577 | } | 592 | } |
578 | }; | 593 | }; |
579 | sink.push(MacroError { file, node: ast, message: message.clone() }); | 594 | acc.push(MacroError { node, message: message.clone() }.into()); |
580 | } | 595 | } |
581 | 596 | ||
582 | DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => { | 597 | DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => { |
583 | let node = ast.to_node(db.upcast()); | 598 | let node = ast.to_node(db.upcast()); |
584 | // Must have a name, otherwise we wouldn't emit it. | 599 | // Must have a name, otherwise we wouldn't emit it. |
585 | let name = node.name().expect("unimplemented builtin macro with no name"); | 600 | let name = node.name().expect("unimplemented builtin macro with no name"); |
586 | let ptr = SyntaxNodePtr::from(AstPtr::new(&name)); | 601 | acc.push( |
587 | 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 | ); | ||
588 | } | 607 | } |
589 | } | 608 | } |
590 | } | 609 | } |
591 | for decl in self.declarations(db) { | 610 | for decl in self.declarations(db) { |
592 | match decl { | 611 | match decl { |
593 | crate::ModuleDef::Function(f) => f.diagnostics(db, sink), | 612 | ModuleDef::Function(f) => f.diagnostics(db, acc), |
594 | crate::ModuleDef::Module(m) => { | 613 | ModuleDef::Module(m) => { |
595 | // Only add diagnostics from inline modules | 614 | // Only add diagnostics from inline modules |
596 | if def_map[m.id.local_id].origin.is_inline() { | 615 | if def_map[m.id.local_id].origin.is_inline() { |
597 | m.diagnostics(db, sink) | 616 | m.diagnostics(db, acc) |
598 | } | 617 | } |
599 | } | 618 | } |
600 | _ => { | 619 | _ => acc.extend(decl.diagnostics(db)), |
601 | decl.diagnostics(db, sink); | ||
602 | } | ||
603 | } | 620 | } |
604 | } | 621 | } |
605 | 622 | ||
606 | for impl_def in self.impl_defs(db) { | 623 | for impl_def in self.impl_defs(db) { |
607 | for item in impl_def.items(db) { | 624 | for item in impl_def.items(db) { |
608 | if let AssocItem::Function(f) = item { | 625 | if let AssocItem::Function(f) = item { |
609 | f.diagnostics(db, sink); | 626 | f.diagnostics(db, acc); |
610 | } | 627 | } |
611 | } | 628 | } |
612 | } | 629 | } |
@@ -1008,41 +1025,191 @@ impl Function { | |||
1008 | db.function_data(self.id).is_async() | 1025 | db.function_data(self.id).is_async() |
1009 | } | 1026 | } |
1010 | 1027 | ||
1011 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | 1028 | pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) { |
1012 | let krate = self.module(db).id.krate(); | 1029 | let krate = self.module(db).id.krate(); |
1013 | 1030 | ||
1014 | 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; |
1015 | for diag in source_map.diagnostics() { | 1032 | for diag in source_map.diagnostics() { |
1016 | match diag { | 1033 | match diag { |
1017 | BodyDiagnostic::InactiveCode { node, cfg, opts } => sink.push(InactiveCode { | 1034 | BodyDiagnostic::InactiveCode { node, cfg, opts } => acc.push( |
1018 | file: node.file_id, | 1035 | InactiveCode { node: node.clone(), cfg: cfg.clone(), opts: opts.clone() } |
1019 | node: node.value.clone(), | 1036 | .into(), |
1020 | cfg: cfg.clone(), | 1037 | ), |
1021 | opts: opts.clone(), | 1038 | BodyDiagnostic::MacroError { node, message } => acc.push( |
1022 | }), | 1039 | MacroError { |
1023 | BodyDiagnostic::MacroError { node, message } => sink.push(MacroError { | 1040 | node: node.clone().map(|it| it.into()), |
1024 | file: node.file_id, | 1041 | message: message.to_string(), |
1025 | node: node.value.clone().into(), | 1042 | } |
1026 | message: message.to_string(), | 1043 | .into(), |
1027 | }), | 1044 | ), |
1028 | BodyDiagnostic::UnresolvedProcMacro { node } => sink.push(UnresolvedProcMacro { | 1045 | BodyDiagnostic::UnresolvedProcMacro { node } => acc.push( |
1029 | file: node.file_id, | 1046 | UnresolvedProcMacro { |
1030 | node: node.value.clone().into(), | 1047 | node: node.clone().map(|it| it.into()), |
1031 | precise_location: None, | 1048 | precise_location: None, |
1032 | macro_name: None, | 1049 | macro_name: None, |
1033 | }), | 1050 | } |
1034 | BodyDiagnostic::UnresolvedMacroCall { node, path } => { | 1051 | .into(), |
1035 | sink.push(UnresolvedMacroCall { | 1052 | ), |
1036 | file: node.file_id, | 1053 | BodyDiagnostic::UnresolvedMacroCall { node, path } => acc.push( |
1037 | node: node.value.clone(), | 1054 | UnresolvedMacroCall { macro_call: node.clone(), path: path.clone() }.into(), |
1038 | path: path.clone(), | 1055 | ), |
1039 | }) | 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()) | ||
1072 | } | ||
1073 | } | ||
1074 | } | ||
1075 | |||
1076 | for expr in hir_ty::diagnostics::missing_unsafe(db, self.id.into()) { | ||
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 | } | ||
1040 | } | 1206 | } |
1041 | } | 1207 | } |
1042 | } | 1208 | } |
1043 | 1209 | ||
1044 | hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink); | 1210 | for diag in hir_ty::diagnostics::validate_module_item(db, krate, self.id.into()) { |
1045 | hir_ty::diagnostics::validate_body(db, self.id.into(), sink); | 1211 | acc.push(diag.into()) |
1212 | } | ||
1046 | } | 1213 | } |
1047 | 1214 | ||
1048 | /// Whether this function declaration has a definition. | 1215 | /// Whether this function declaration has a definition. |
@@ -1450,6 +1617,20 @@ impl AssocItem { | |||
1450 | _ => None, | 1617 | _ => None, |
1451 | } | 1618 | } |
1452 | } | 1619 | } |
1620 | |||
1621 | pub fn containing_trait_impl(self, db: &dyn HirDatabase) -> Option<Trait> { | ||
1622 | match self.container(db) { | ||
1623 | AssocItemContainer::Impl(i) => i.trait_(db), | ||
1624 | _ => None, | ||
1625 | } | ||
1626 | } | ||
1627 | |||
1628 | pub fn containing_trait_or_trait_impl(self, db: &dyn HirDatabase) -> Option<Trait> { | ||
1629 | match self.container(db) { | ||
1630 | AssocItemContainer::Trait(t) => Some(t), | ||
1631 | AssocItemContainer::Impl(i) => i.trait_(db), | ||
1632 | } | ||
1633 | } | ||
1453 | } | 1634 | } |
1454 | 1635 | ||
1455 | impl HasVisibility for AssocItem { | 1636 | impl HasVisibility for AssocItem { |
@@ -1747,7 +1928,7 @@ impl Impl { | |||
1747 | } | 1928 | } |
1748 | 1929 | ||
1749 | 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> { |
1750 | let def_crates = match def_crates(db, &ty, krate) { | 1931 | let def_crates = match method_resolution::def_crates(db, &ty, krate) { |
1751 | Some(def_crates) => def_crates, | 1932 | Some(def_crates) => def_crates, |
1752 | None => return Vec::new(), | 1933 | None => return Vec::new(), |
1753 | }; | 1934 | }; |
@@ -2153,7 +2334,7 @@ impl Type { | |||
2153 | krate: Crate, | 2334 | krate: Crate, |
2154 | mut callback: impl FnMut(AssocItem) -> Option<T>, | 2335 | mut callback: impl FnMut(AssocItem) -> Option<T>, |
2155 | ) -> Option<T> { | 2336 | ) -> Option<T> { |
2156 | for krate in def_crates(db, &self.ty, krate.id)? { | 2337 | for krate in method_resolution::def_crates(db, &self.ty, krate.id)? { |
2157 | let impls = db.inherent_impls_in_crate(krate); | 2338 | let impls = db.inherent_impls_in_crate(krate); |
2158 | 2339 | ||
2159 | for impl_def in impls.for_self_ty(&self.ty) { | 2340 | for impl_def in impls.for_self_ty(&self.ty) { |
@@ -2185,6 +2366,7 @@ impl Type { | |||
2185 | name: Option<&Name>, | 2366 | name: Option<&Name>, |
2186 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, | 2367 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, |
2187 | ) -> Option<T> { | 2368 | ) -> Option<T> { |
2369 | let _p = profile::span("iterate_method_candidates"); | ||
2188 | // There should be no inference vars in types passed here | 2370 | // There should be no inference vars in types passed here |
2189 | // FIXME check that? | 2371 | // FIXME check that? |
2190 | // FIXME replace Unknown by bound vars here | 2372 | // FIXME replace Unknown by bound vars here |
@@ -2218,6 +2400,7 @@ impl Type { | |||
2218 | name: Option<&Name>, | 2400 | name: Option<&Name>, |
2219 | mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, | 2401 | mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, |
2220 | ) -> Option<T> { | 2402 | ) -> Option<T> { |
2403 | let _p = profile::span("iterate_path_candidates"); | ||
2221 | let canonical = hir_ty::replace_errors_with_variables(&self.ty); | 2404 | let canonical = hir_ty::replace_errors_with_variables(&self.ty); |
2222 | 2405 | ||
2223 | let env = self.env.clone(); | 2406 | let env = self.env.clone(); |
@@ -2255,6 +2438,7 @@ impl Type { | |||
2255 | &'a self, | 2438 | &'a self, |
2256 | db: &'a dyn HirDatabase, | 2439 | db: &'a dyn HirDatabase, |
2257 | ) -> impl Iterator<Item = Trait> + 'a { | 2440 | ) -> impl Iterator<Item = Trait> + 'a { |
2441 | let _p = profile::span("applicable_inherent_traits"); | ||
2258 | self.autoderef(db) | 2442 | self.autoderef(db) |
2259 | .filter_map(|derefed_type| derefed_type.ty.dyn_trait()) | 2443 | .filter_map(|derefed_type| derefed_type.ty.dyn_trait()) |
2260 | .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id)) | 2444 | .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id)) |
@@ -2327,13 +2511,13 @@ impl Type { | |||
2327 | match ty.kind(&Interner) { | 2511 | match ty.kind(&Interner) { |
2328 | TyKind::Adt(_, substs) => { | 2512 | TyKind::Adt(_, substs) => { |
2329 | cb(type_.derived(ty.clone())); | 2513 | cb(type_.derived(ty.clone())); |
2330 | walk_substs(db, type_, &substs, cb); | 2514 | walk_substs(db, type_, substs, cb); |
2331 | } | 2515 | } |
2332 | TyKind::AssociatedType(_, substs) => { | 2516 | TyKind::AssociatedType(_, substs) => { |
2333 | if let Some(_) = ty.associated_type_parent_trait(db) { | 2517 | if let Some(_) = ty.associated_type_parent_trait(db) { |
2334 | cb(type_.derived(ty.clone())); | 2518 | cb(type_.derived(ty.clone())); |
2335 | } | 2519 | } |
2336 | walk_substs(db, type_, &substs, cb); | 2520 | walk_substs(db, type_, substs, cb); |
2337 | } | 2521 | } |
2338 | TyKind::OpaqueType(_, subst) => { | 2522 | TyKind::OpaqueType(_, subst) => { |
2339 | if let Some(bounds) = ty.impl_trait_bounds(db) { | 2523 | if let Some(bounds) = ty.impl_trait_bounds(db) { |
@@ -2373,7 +2557,7 @@ impl Type { | |||
2373 | TyKind::FnDef(_, substs) | 2557 | TyKind::FnDef(_, substs) |
2374 | | TyKind::Tuple(_, substs) | 2558 | | TyKind::Tuple(_, substs) |
2375 | | TyKind::Closure(.., substs) => { | 2559 | | TyKind::Closure(.., substs) => { |
2376 | walk_substs(db, type_, &substs, cb); | 2560 | walk_substs(db, type_, substs, cb); |
2377 | } | 2561 | } |
2378 | TyKind::Function(hir_ty::FnPointer { substitution, .. }) => { | 2562 | TyKind::Function(hir_ty::FnPointer { substitution, .. }) => { |
2379 | walk_substs(db, type_, &substitution.0, cb); | 2563 | walk_substs(db, type_, &substitution.0, cb); |
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index d522d5245..613266e07 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs | |||
@@ -192,7 +192,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
192 | node: &SyntaxNode, | 192 | node: &SyntaxNode, |
193 | offset: TextSize, | 193 | offset: TextSize, |
194 | ) -> Option<N> { | 194 | ) -> Option<N> { |
195 | if let Some(it) = find_node_at_offset(&node, offset) { | 195 | if let Some(it) = find_node_at_offset(node, offset) { |
196 | return Some(it); | 196 | return Some(it); |
197 | } | 197 | } |
198 | 198 | ||
@@ -744,7 +744,7 @@ impl<'db> SemanticsImpl<'db> { | |||
744 | return None; | 744 | return None; |
745 | } | 745 | } |
746 | 746 | ||
747 | let func = self.resolve_method_call(&method_call_expr).map(Function::from)?; | 747 | let func = self.resolve_method_call(method_call_expr).map(Function::from)?; |
748 | let res = match func.self_param(self.db)?.access(self.db) { | 748 | let res = match func.self_param(self.db)?.access(self.db) { |
749 | Access::Shared | Access::Exclusive => true, | 749 | Access::Shared | Access::Exclusive => true, |
750 | Access::Owned => false, | 750 | Access::Owned => false, |
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 37a050415..c9744d81d 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs | |||
@@ -222,7 +222,7 @@ impl SourceAnalyzer { | |||
222 | Pat::Path(path) => path, | 222 | Pat::Path(path) => path, |
223 | _ => return None, | 223 | _ => return None, |
224 | }; | 224 | }; |
225 | let res = resolve_hir_path(db, &self.resolver, &path)?; | 225 | let res = resolve_hir_path(db, &self.resolver, path)?; |
226 | match res { | 226 | match res { |
227 | PathResolution::Def(def) => Some(def), | 227 | PathResolution::Def(def) => Some(def), |
228 | _ => None, | 228 | _ => None, |
@@ -329,7 +329,7 @@ impl SourceAnalyzer { | |||
329 | 329 | ||
330 | let (variant, missing_fields, _exhaustive) = | 330 | let (variant, missing_fields, _exhaustive) = |
331 | record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?; | 331 | record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?; |
332 | let res = self.missing_fields(db, krate, &substs, variant, missing_fields); | 332 | let res = self.missing_fields(db, krate, substs, variant, missing_fields); |
333 | Some(res) | 333 | Some(res) |
334 | } | 334 | } |
335 | 335 | ||
@@ -347,7 +347,7 @@ impl SourceAnalyzer { | |||
347 | 347 | ||
348 | let (variant, missing_fields, _exhaustive) = | 348 | let (variant, missing_fields, _exhaustive) = |
349 | record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?; | 349 | record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?; |
350 | let res = self.missing_fields(db, krate, &substs, variant, missing_fields); | 350 | let res = self.missing_fields(db, krate, substs, variant, missing_fields); |
351 | Some(res) | 351 | Some(res) |
352 | } | 352 | } |
353 | 353 | ||