diff options
Diffstat (limited to 'crates/hir/src')
-rw-r--r-- | crates/hir/src/display.rs | 441 | ||||
-rw-r--r-- | crates/hir/src/lib.rs | 256 | ||||
-rw-r--r-- | crates/hir/src/semantics.rs | 8 | ||||
-rw-r--r-- | crates/hir/src/semantics/source_to_def.rs | 22 | ||||
-rw-r--r-- | crates/hir/src/source_analyzer.rs | 5 |
5 files changed, 637 insertions, 95 deletions
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs new file mode 100644 index 000000000..44cdcc296 --- /dev/null +++ b/crates/hir/src/display.rs | |||
@@ -0,0 +1,441 @@ | |||
1 | //! HirDisplay implementations for various hir types. | ||
2 | use hir_def::{ | ||
3 | adt::VariantData, | ||
4 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, | ||
5 | type_ref::{TypeBound, TypeRef}, | ||
6 | AdtId, GenericDefId, | ||
7 | }; | ||
8 | use hir_ty::display::{ | ||
9 | write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError, | ||
10 | HirFormatter, | ||
11 | }; | ||
12 | use syntax::ast::{self, NameOwner}; | ||
13 | |||
14 | use crate::{ | ||
15 | Const, ConstParam, Enum, Field, Function, HasVisibility, Module, Static, Struct, Substs, Trait, | ||
16 | Type, TypeAlias, TypeParam, Union, Variant, | ||
17 | }; | ||
18 | |||
19 | impl HirDisplay for Function { | ||
20 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
21 | let data = f.db.function_data(self.id); | ||
22 | write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; | ||
23 | let qual = &data.qualifier; | ||
24 | if qual.is_default { | ||
25 | write!(f, "default ")?; | ||
26 | } | ||
27 | if qual.is_const { | ||
28 | write!(f, "const ")?; | ||
29 | } | ||
30 | if qual.is_async { | ||
31 | write!(f, "async ")?; | ||
32 | } | ||
33 | if qual.is_unsafe { | ||
34 | write!(f, "unsafe ")?; | ||
35 | } | ||
36 | if let Some(abi) = &qual.abi { | ||
37 | // FIXME: String escape? | ||
38 | write!(f, "extern \"{}\" ", abi)?; | ||
39 | } | ||
40 | write!(f, "fn {}", data.name)?; | ||
41 | |||
42 | write_generic_params(GenericDefId::FunctionId(self.id), f)?; | ||
43 | |||
44 | write!(f, "(")?; | ||
45 | |||
46 | let write_self_param = |ty: &TypeRef, f: &mut HirFormatter| match ty { | ||
47 | TypeRef::Path(p) if p.is_self_type() => write!(f, "self"), | ||
48 | TypeRef::Reference(inner, lifetime, mut_) if matches!(&**inner,TypeRef::Path(p) if p.is_self_type()) => | ||
49 | { | ||
50 | write!(f, "&")?; | ||
51 | if let Some(lifetime) = lifetime { | ||
52 | write!(f, "{} ", lifetime.name)?; | ||
53 | } | ||
54 | if let hir_def::type_ref::Mutability::Mut = mut_ { | ||
55 | write!(f, "mut ")?; | ||
56 | } | ||
57 | write!(f, "self") | ||
58 | } | ||
59 | _ => { | ||
60 | write!(f, "self: ")?; | ||
61 | ty.hir_fmt(f) | ||
62 | } | ||
63 | }; | ||
64 | |||
65 | let mut first = true; | ||
66 | for (param, type_ref) in self.assoc_fn_params(f.db).into_iter().zip(&data.params) { | ||
67 | if !first { | ||
68 | write!(f, ", ")?; | ||
69 | } else { | ||
70 | first = false; | ||
71 | if data.has_self_param { | ||
72 | write_self_param(type_ref, f)?; | ||
73 | continue; | ||
74 | } | ||
75 | } | ||
76 | match param.pattern_source(f.db) { | ||
77 | Some(ast::Pat::IdentPat(p)) if p.name().is_some() => { | ||
78 | write!(f, "{}: ", p.name().unwrap())? | ||
79 | } | ||
80 | _ => write!(f, "_: ")?, | ||
81 | } | ||
82 | // FIXME: Use resolved `param.ty` or raw `type_ref`? | ||
83 | // The former will ignore lifetime arguments currently. | ||
84 | type_ref.hir_fmt(f)?; | ||
85 | } | ||
86 | write!(f, ")")?; | ||
87 | |||
88 | // `FunctionData::ret_type` will be `::core::future::Future<Output = ...>` for async fns. | ||
89 | // Use ugly pattern match to strip the Future trait. | ||
90 | // Better way? | ||
91 | let ret_type = if !qual.is_async { | ||
92 | &data.ret_type | ||
93 | } else { | ||
94 | match &data.ret_type { | ||
95 | TypeRef::ImplTrait(bounds) => match &bounds[0] { | ||
96 | TypeBound::Path(path) => { | ||
97 | path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings | ||
98 | [0] | ||
99 | .type_ref | ||
100 | .as_ref() | ||
101 | .unwrap() | ||
102 | } | ||
103 | _ => panic!("Async fn ret_type should be impl Future"), | ||
104 | }, | ||
105 | _ => panic!("Async fn ret_type should be impl Future"), | ||
106 | } | ||
107 | }; | ||
108 | |||
109 | match ret_type { | ||
110 | TypeRef::Tuple(tup) if tup.is_empty() => {} | ||
111 | ty => { | ||
112 | write!(f, " -> ")?; | ||
113 | ty.hir_fmt(f)?; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | write_where_clause(GenericDefId::FunctionId(self.id), f)?; | ||
118 | |||
119 | Ok(()) | ||
120 | } | ||
121 | } | ||
122 | |||
123 | impl HirDisplay for Struct { | ||
124 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
125 | write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; | ||
126 | write!(f, "struct ")?; | ||
127 | write!(f, "{}", self.name(f.db))?; | ||
128 | let def_id = GenericDefId::AdtId(AdtId::StructId(self.id)); | ||
129 | write_generic_params(def_id, f)?; | ||
130 | write_where_clause(def_id, f)?; | ||
131 | Ok(()) | ||
132 | } | ||
133 | } | ||
134 | |||
135 | impl HirDisplay for Enum { | ||
136 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
137 | write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; | ||
138 | write!(f, "enum ")?; | ||
139 | write!(f, "{}", self.name(f.db))?; | ||
140 | let def_id = GenericDefId::AdtId(AdtId::EnumId(self.id)); | ||
141 | write_generic_params(def_id, f)?; | ||
142 | write_where_clause(def_id, f)?; | ||
143 | Ok(()) | ||
144 | } | ||
145 | } | ||
146 | |||
147 | impl HirDisplay for Union { | ||
148 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
149 | write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; | ||
150 | write!(f, "union ")?; | ||
151 | write!(f, "{}", self.name(f.db))?; | ||
152 | let def_id = GenericDefId::AdtId(AdtId::UnionId(self.id)); | ||
153 | write_generic_params(def_id, f)?; | ||
154 | write_where_clause(def_id, f)?; | ||
155 | Ok(()) | ||
156 | } | ||
157 | } | ||
158 | |||
159 | impl HirDisplay for Field { | ||
160 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
161 | write_visibility(self.parent.module(f.db).id, self.visibility(f.db), f)?; | ||
162 | write!(f, "{}: ", self.name(f.db))?; | ||
163 | self.signature_ty(f.db).hir_fmt(f) | ||
164 | } | ||
165 | } | ||
166 | |||
167 | impl HirDisplay for Variant { | ||
168 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
169 | write!(f, "{}", self.name(f.db))?; | ||
170 | let data = self.variant_data(f.db); | ||
171 | match &*data { | ||
172 | VariantData::Unit => {} | ||
173 | VariantData::Tuple(fields) => { | ||
174 | write!(f, "(")?; | ||
175 | let mut first = true; | ||
176 | for (_, field) in fields.iter() { | ||
177 | if first { | ||
178 | first = false; | ||
179 | } else { | ||
180 | write!(f, ", ")?; | ||
181 | } | ||
182 | // Enum variant fields must be pub. | ||
183 | field.type_ref.hir_fmt(f)?; | ||
184 | } | ||
185 | write!(f, ")")?; | ||
186 | } | ||
187 | VariantData::Record(fields) => { | ||
188 | write!(f, " {{")?; | ||
189 | let mut first = true; | ||
190 | for (_, field) in fields.iter() { | ||
191 | if first { | ||
192 | first = false; | ||
193 | write!(f, " ")?; | ||
194 | } else { | ||
195 | write!(f, ", ")?; | ||
196 | } | ||
197 | // Enum variant fields must be pub. | ||
198 | write!(f, "{}: ", field.name)?; | ||
199 | field.type_ref.hir_fmt(f)?; | ||
200 | } | ||
201 | write!(f, " }}")?; | ||
202 | } | ||
203 | } | ||
204 | Ok(()) | ||
205 | } | ||
206 | } | ||
207 | |||
208 | impl HirDisplay for Type { | ||
209 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
210 | self.ty.value.hir_fmt(f) | ||
211 | } | ||
212 | } | ||
213 | |||
214 | impl HirDisplay for TypeParam { | ||
215 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
216 | write!(f, "{}", self.name(f.db))?; | ||
217 | let bounds = f.db.generic_predicates_for_param(self.id); | ||
218 | let substs = Substs::type_params(f.db, self.id.parent); | ||
219 | let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>(); | ||
220 | if !(predicates.is_empty() || f.omit_verbose_types()) { | ||
221 | write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?; | ||
222 | } | ||
223 | Ok(()) | ||
224 | } | ||
225 | } | ||
226 | |||
227 | impl HirDisplay for ConstParam { | ||
228 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
229 | write!(f, "const {}: ", self.name(f.db))?; | ||
230 | self.ty(f.db).hir_fmt(f) | ||
231 | } | ||
232 | } | ||
233 | |||
234 | fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
235 | let params = f.db.generic_params(def); | ||
236 | if params.lifetimes.is_empty() | ||
237 | && params.consts.is_empty() | ||
238 | && params | ||
239 | .types | ||
240 | .iter() | ||
241 | .all(|(_, param)| !matches!(param.provenance, TypeParamProvenance::TypeParamList)) | ||
242 | { | ||
243 | return Ok(()); | ||
244 | } | ||
245 | write!(f, "<")?; | ||
246 | |||
247 | let mut first = true; | ||
248 | let mut delim = |f: &mut HirFormatter| { | ||
249 | if first { | ||
250 | first = false; | ||
251 | Ok(()) | ||
252 | } else { | ||
253 | write!(f, ", ") | ||
254 | } | ||
255 | }; | ||
256 | for (_, lifetime) in params.lifetimes.iter() { | ||
257 | delim(f)?; | ||
258 | write!(f, "{}", lifetime.name)?; | ||
259 | } | ||
260 | for (_, ty) in params.types.iter() { | ||
261 | if ty.provenance != TypeParamProvenance::TypeParamList { | ||
262 | continue; | ||
263 | } | ||
264 | if let Some(name) = &ty.name { | ||
265 | delim(f)?; | ||
266 | write!(f, "{}", name)?; | ||
267 | if let Some(default) = &ty.default { | ||
268 | write!(f, " = ")?; | ||
269 | default.hir_fmt(f)?; | ||
270 | } | ||
271 | } | ||
272 | } | ||
273 | for (_, konst) in params.consts.iter() { | ||
274 | delim(f)?; | ||
275 | write!(f, "const {}: ", konst.name)?; | ||
276 | konst.ty.hir_fmt(f)?; | ||
277 | } | ||
278 | |||
279 | write!(f, ">")?; | ||
280 | Ok(()) | ||
281 | } | ||
282 | |||
283 | fn write_where_clause(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
284 | let params = f.db.generic_params(def); | ||
285 | if params.where_predicates.is_empty() { | ||
286 | return Ok(()); | ||
287 | } | ||
288 | |||
289 | let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter| match target { | ||
290 | WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f), | ||
291 | WherePredicateTypeTarget::TypeParam(id) => match ¶ms.types[*id].name { | ||
292 | Some(name) => write!(f, "{}", name), | ||
293 | None => write!(f, "{{unnamed}}"), | ||
294 | }, | ||
295 | }; | ||
296 | |||
297 | write!(f, "\nwhere")?; | ||
298 | |||
299 | for (pred_idx, pred) in params.where_predicates.iter().enumerate() { | ||
300 | let prev_pred = | ||
301 | if pred_idx == 0 { None } else { Some(¶ms.where_predicates[pred_idx - 1]) }; | ||
302 | |||
303 | let new_predicate = |f: &mut HirFormatter| { | ||
304 | write!(f, "{}", if pred_idx == 0 { "\n " } else { ",\n " }) | ||
305 | }; | ||
306 | |||
307 | match pred { | ||
308 | WherePredicate::TypeBound { target, bound } => { | ||
309 | if matches!(prev_pred, Some(WherePredicate::TypeBound { target: target_, .. }) if target_ == target) | ||
310 | { | ||
311 | write!(f, " + ")?; | ||
312 | } else { | ||
313 | new_predicate(f)?; | ||
314 | write_target(target, f)?; | ||
315 | write!(f, ": ")?; | ||
316 | } | ||
317 | bound.hir_fmt(f)?; | ||
318 | } | ||
319 | WherePredicate::Lifetime { target, bound } => { | ||
320 | if matches!(prev_pred, Some(WherePredicate::Lifetime { target: target_, .. }) if target_ == target) | ||
321 | { | ||
322 | write!(f, " + {}", bound.name)?; | ||
323 | } else { | ||
324 | new_predicate(f)?; | ||
325 | write!(f, "{}: {}", target.name, bound.name)?; | ||
326 | } | ||
327 | } | ||
328 | WherePredicate::ForLifetime { lifetimes, target, bound } => { | ||
329 | if matches!( | ||
330 | prev_pred, | ||
331 | Some(WherePredicate::ForLifetime { lifetimes: lifetimes_, target: target_, .. }) | ||
332 | if lifetimes_ == lifetimes && target_ == target, | ||
333 | ) { | ||
334 | write!(f, " + ")?; | ||
335 | } else { | ||
336 | new_predicate(f)?; | ||
337 | write!(f, "for<")?; | ||
338 | for (idx, lifetime) in lifetimes.iter().enumerate() { | ||
339 | if idx != 0 { | ||
340 | write!(f, ", ")?; | ||
341 | } | ||
342 | write!(f, "{}", lifetime)?; | ||
343 | } | ||
344 | write!(f, "> ")?; | ||
345 | write_target(target, f)?; | ||
346 | write!(f, ": ")?; | ||
347 | } | ||
348 | bound.hir_fmt(f)?; | ||
349 | } | ||
350 | } | ||
351 | } | ||
352 | |||
353 | // End of final predicate. There must be at least one predicate here. | ||
354 | write!(f, ",")?; | ||
355 | |||
356 | Ok(()) | ||
357 | } | ||
358 | |||
359 | impl HirDisplay for Const { | ||
360 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
361 | write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; | ||
362 | let data = f.db.const_data(self.id); | ||
363 | write!(f, "const ")?; | ||
364 | match &data.name { | ||
365 | Some(name) => write!(f, "{}: ", name)?, | ||
366 | None => write!(f, "_: ")?, | ||
367 | } | ||
368 | data.type_ref.hir_fmt(f)?; | ||
369 | Ok(()) | ||
370 | } | ||
371 | } | ||
372 | |||
373 | impl HirDisplay for Static { | ||
374 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
375 | write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; | ||
376 | let data = f.db.static_data(self.id); | ||
377 | write!(f, "static ")?; | ||
378 | if data.mutable { | ||
379 | write!(f, "mut ")?; | ||
380 | } | ||
381 | match &data.name { | ||
382 | Some(name) => write!(f, "{}: ", name)?, | ||
383 | None => write!(f, "_: ")?, | ||
384 | } | ||
385 | data.type_ref.hir_fmt(f)?; | ||
386 | Ok(()) | ||
387 | } | ||
388 | } | ||
389 | |||
390 | impl HirDisplay for Trait { | ||
391 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
392 | write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; | ||
393 | let data = f.db.trait_data(self.id); | ||
394 | if data.is_unsafe { | ||
395 | write!(f, "unsafe ")?; | ||
396 | } | ||
397 | if data.is_auto { | ||
398 | write!(f, "auto ")?; | ||
399 | } | ||
400 | write!(f, "trait {}", data.name)?; | ||
401 | let def_id = GenericDefId::TraitId(self.id); | ||
402 | write_generic_params(def_id, f)?; | ||
403 | if !data.bounds.is_empty() { | ||
404 | write!(f, ": ")?; | ||
405 | f.write_joined(&*data.bounds, " + ")?; | ||
406 | } | ||
407 | write_where_clause(def_id, f)?; | ||
408 | Ok(()) | ||
409 | } | ||
410 | } | ||
411 | |||
412 | impl HirDisplay for TypeAlias { | ||
413 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
414 | write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; | ||
415 | let data = f.db.type_alias_data(self.id); | ||
416 | write!(f, "type {}", data.name)?; | ||
417 | if !data.bounds.is_empty() { | ||
418 | write!(f, ": ")?; | ||
419 | f.write_joined(&data.bounds, " + ")?; | ||
420 | } | ||
421 | if let Some(ty) = &data.type_ref { | ||
422 | write!(f, " = ")?; | ||
423 | ty.hir_fmt(f)?; | ||
424 | } | ||
425 | Ok(()) | ||
426 | } | ||
427 | } | ||
428 | |||
429 | impl HirDisplay for Module { | ||
430 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
431 | // FIXME: Module doesn't have visibility saved in data. | ||
432 | match self.name(f.db) { | ||
433 | Some(name) => write!(f, "mod {}", name), | ||
434 | None if self.crate_root(f.db) == *self => match self.krate().display_name(f.db) { | ||
435 | Some(name) => write!(f, "extern crate {}", name), | ||
436 | None => write!(f, "extern crate {{unknown}}"), | ||
437 | }, | ||
438 | None => write!(f, "mod {{unnamed}}"), | ||
439 | } | ||
440 | } | ||
441 | } | ||
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 8d082994a..f0bc2c7b9 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -29,6 +29,8 @@ mod has_source; | |||
29 | pub mod diagnostics; | 29 | pub mod diagnostics; |
30 | pub mod db; | 30 | pub mod db; |
31 | 31 | ||
32 | mod display; | ||
33 | |||
32 | use std::{iter, sync::Arc}; | 34 | use std::{iter, sync::Arc}; |
33 | 35 | ||
34 | use arrayvec::ArrayVec; | 36 | use arrayvec::ArrayVec; |
@@ -50,12 +52,13 @@ use hir_def::{ | |||
50 | use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; | 52 | use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; |
51 | use hir_ty::{ | 53 | use hir_ty::{ |
52 | autoderef, | 54 | autoderef, |
53 | display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter}, | 55 | method_resolution::{self, TyFingerprint}, |
54 | method_resolution, | 56 | primitive::UintTy, |
57 | to_assoc_type_id, | ||
55 | traits::{FnTrait, Solution, SolutionVariables}, | 58 | traits::{FnTrait, Solution, SolutionVariables}, |
56 | AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate, | 59 | AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate, |
57 | InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment, | 60 | InEnvironment, Interner, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, Ty, |
58 | Ty, TyDefId, TyVariableKind, | 61 | TyDefId, TyKind, TyVariableKind, |
59 | }; | 62 | }; |
60 | use rustc_hash::FxHashSet; | 63 | use rustc_hash::FxHashSet; |
61 | use stdx::{format_to, impl_from}; | 64 | use stdx::{format_to, impl_from}; |
@@ -266,8 +269,7 @@ impl ModuleDef { | |||
266 | } | 269 | } |
267 | 270 | ||
268 | pub fn canonical_path(&self, db: &dyn HirDatabase) -> Option<String> { | 271 | pub fn canonical_path(&self, db: &dyn HirDatabase) -> Option<String> { |
269 | let mut segments = Vec::new(); | 272 | let mut segments = vec![self.name(db)?.to_string()]; |
270 | segments.push(self.name(db)?.to_string()); | ||
271 | for m in self.module(db)?.path_to_root(db) { | 273 | for m in self.module(db)?.path_to_root(db) { |
272 | segments.extend(m.name(db).map(|it| it.to_string())) | 274 | segments.extend(m.name(db).map(|it| it.to_string())) |
273 | } | 275 | } |
@@ -571,6 +573,12 @@ impl Struct { | |||
571 | } | 573 | } |
572 | } | 574 | } |
573 | 575 | ||
576 | impl HasVisibility for Struct { | ||
577 | fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||
578 | db.struct_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast())) | ||
579 | } | ||
580 | } | ||
581 | |||
574 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 582 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
575 | pub struct Union { | 583 | pub struct Union { |
576 | pub(crate) id: UnionId, | 584 | pub(crate) id: UnionId, |
@@ -603,6 +611,12 @@ impl Union { | |||
603 | } | 611 | } |
604 | } | 612 | } |
605 | 613 | ||
614 | impl HasVisibility for Union { | ||
615 | fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||
616 | db.union_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast())) | ||
617 | } | ||
618 | } | ||
619 | |||
606 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 620 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
607 | pub struct Enum { | 621 | pub struct Enum { |
608 | pub(crate) id: EnumId, | 622 | pub(crate) id: EnumId, |
@@ -630,6 +644,12 @@ impl Enum { | |||
630 | } | 644 | } |
631 | } | 645 | } |
632 | 646 | ||
647 | impl HasVisibility for Enum { | ||
648 | fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||
649 | db.enum_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast())) | ||
650 | } | ||
651 | } | ||
652 | |||
633 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 653 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
634 | pub struct Variant { | 654 | pub struct Variant { |
635 | pub(crate) parent: Enum, | 655 | pub(crate) parent: Enum, |
@@ -677,7 +697,7 @@ impl_from!(Struct, Union, Enum for Adt); | |||
677 | impl Adt { | 697 | impl Adt { |
678 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { | 698 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { |
679 | let subst = db.generic_defaults(self.into()); | 699 | let subst = db.generic_defaults(self.into()); |
680 | subst.iter().any(|ty| &ty.value == &Ty::Unknown) | 700 | subst.iter().any(|ty| ty.value.is_unknown()) |
681 | } | 701 | } |
682 | 702 | ||
683 | /// Turns this ADT into a type. Any type parameters of the ADT will be | 703 | /// Turns this ADT into a type. Any type parameters of the ADT will be |
@@ -696,8 +716,8 @@ impl Adt { | |||
696 | } | 716 | } |
697 | } | 717 | } |
698 | 718 | ||
699 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | 719 | pub fn krate(self, db: &dyn HirDatabase) -> Crate { |
700 | Some(self.module(db).krate()) | 720 | self.module(db).krate() |
701 | } | 721 | } |
702 | 722 | ||
703 | pub fn name(self, db: &dyn HirDatabase) -> Name { | 723 | pub fn name(self, db: &dyn HirDatabase) -> Name { |
@@ -802,7 +822,7 @@ impl Function { | |||
802 | let krate = self.id.lookup(db.upcast()).container.module(db.upcast()).krate(); | 822 | let krate = self.id.lookup(db.upcast()).container.module(db.upcast()).krate(); |
803 | let ret_type = &db.function_data(self.id).ret_type; | 823 | let ret_type = &db.function_data(self.id).ret_type; |
804 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); | 824 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); |
805 | let ty = Ty::from_hir_ext(&ctx, ret_type).0; | 825 | let ty = ctx.lower_ty(ret_type); |
806 | Type::new_with_resolver_inner(db, krate, &resolver, ty) | 826 | Type::new_with_resolver_inner(db, krate, &resolver, ty) |
807 | } | 827 | } |
808 | 828 | ||
@@ -817,19 +837,20 @@ impl Function { | |||
817 | let resolver = self.id.resolver(db.upcast()); | 837 | let resolver = self.id.resolver(db.upcast()); |
818 | let krate = self.id.lookup(db.upcast()).container.module(db.upcast()).krate(); | 838 | let krate = self.id.lookup(db.upcast()).container.module(db.upcast()).krate(); |
819 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); | 839 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); |
820 | let environment = TraitEnvironment::lower(db, &resolver); | 840 | let environment = db.trait_environment(self.id.into()); |
821 | db.function_data(self.id) | 841 | db.function_data(self.id) |
822 | .params | 842 | .params |
823 | .iter() | 843 | .iter() |
824 | .map(|type_ref| { | 844 | .enumerate() |
845 | .map(|(idx, type_ref)| { | ||
825 | let ty = Type { | 846 | let ty = Type { |
826 | krate, | 847 | krate, |
827 | ty: InEnvironment { | 848 | ty: InEnvironment { |
828 | value: Ty::from_hir_ext(&ctx, type_ref).0, | 849 | value: ctx.lower_ty(type_ref), |
829 | environment: environment.clone(), | 850 | environment: environment.clone(), |
830 | }, | 851 | }, |
831 | }; | 852 | }; |
832 | Param { ty } | 853 | Param { func: self, ty, idx } |
833 | }) | 854 | }) |
834 | .collect() | 855 | .collect() |
835 | } | 856 | } |
@@ -843,7 +864,7 @@ impl Function { | |||
843 | } | 864 | } |
844 | 865 | ||
845 | pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { | 866 | pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { |
846 | db.function_data(self.id).is_unsafe | 867 | db.function_data(self.id).qualifier.is_unsafe |
847 | } | 868 | } |
848 | 869 | ||
849 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | 870 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { |
@@ -892,6 +913,9 @@ impl From<hir_ty::Mutability> for Access { | |||
892 | 913 | ||
893 | #[derive(Debug)] | 914 | #[derive(Debug)] |
894 | pub struct Param { | 915 | pub struct Param { |
916 | func: Function, | ||
917 | /// The index in parameter list, including self parameter. | ||
918 | idx: usize, | ||
895 | ty: Type, | 919 | ty: Type, |
896 | } | 920 | } |
897 | 921 | ||
@@ -899,6 +923,15 @@ impl Param { | |||
899 | pub fn ty(&self) -> &Type { | 923 | pub fn ty(&self) -> &Type { |
900 | &self.ty | 924 | &self.ty |
901 | } | 925 | } |
926 | |||
927 | pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat> { | ||
928 | let params = self.func.source(db)?.value.param_list()?; | ||
929 | if params.self_param().is_some() { | ||
930 | params.params().nth(self.idx.checked_sub(1)?)?.pat() | ||
931 | } else { | ||
932 | params.params().nth(self.idx)?.pat() | ||
933 | } | ||
934 | } | ||
902 | } | 935 | } |
903 | 936 | ||
904 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 937 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -956,6 +989,10 @@ impl Const { | |||
956 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | 989 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { |
957 | db.const_data(self.id).name.clone() | 990 | db.const_data(self.id).name.clone() |
958 | } | 991 | } |
992 | |||
993 | pub fn type_ref(self, db: &dyn HirDatabase) -> TypeRef { | ||
994 | db.const_data(self.id).type_ref.clone() | ||
995 | } | ||
959 | } | 996 | } |
960 | 997 | ||
961 | impl HasVisibility for Const { | 998 | impl HasVisibility for Const { |
@@ -989,6 +1026,12 @@ impl Static { | |||
989 | } | 1026 | } |
990 | } | 1027 | } |
991 | 1028 | ||
1029 | impl HasVisibility for Static { | ||
1030 | fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||
1031 | db.static_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast())) | ||
1032 | } | ||
1033 | } | ||
1034 | |||
992 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 1035 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
993 | pub struct Trait { | 1036 | pub struct Trait { |
994 | pub(crate) id: TraitId, | 1037 | pub(crate) id: TraitId, |
@@ -1008,7 +1051,13 @@ impl Trait { | |||
1008 | } | 1051 | } |
1009 | 1052 | ||
1010 | pub fn is_auto(self, db: &dyn HirDatabase) -> bool { | 1053 | pub fn is_auto(self, db: &dyn HirDatabase) -> bool { |
1011 | db.trait_data(self.id).auto | 1054 | db.trait_data(self.id).is_auto |
1055 | } | ||
1056 | } | ||
1057 | |||
1058 | impl HasVisibility for Trait { | ||
1059 | fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||
1060 | db.trait_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast())) | ||
1012 | } | 1061 | } |
1013 | } | 1062 | } |
1014 | 1063 | ||
@@ -1020,15 +1069,15 @@ pub struct TypeAlias { | |||
1020 | impl TypeAlias { | 1069 | impl TypeAlias { |
1021 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { | 1070 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { |
1022 | let subst = db.generic_defaults(self.id.into()); | 1071 | let subst = db.generic_defaults(self.id.into()); |
1023 | subst.iter().any(|ty| &ty.value == &Ty::Unknown) | 1072 | subst.iter().any(|ty| ty.value.is_unknown()) |
1024 | } | 1073 | } |
1025 | 1074 | ||
1026 | pub fn module(self, db: &dyn HirDatabase) -> Module { | 1075 | pub fn module(self, db: &dyn HirDatabase) -> Module { |
1027 | Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } | 1076 | Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } |
1028 | } | 1077 | } |
1029 | 1078 | ||
1030 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | 1079 | pub fn krate(self, db: &dyn HirDatabase) -> Crate { |
1031 | Some(self.module(db).krate()) | 1080 | self.module(db).krate() |
1032 | } | 1081 | } |
1033 | 1082 | ||
1034 | pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> { | 1083 | pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> { |
@@ -1392,7 +1441,7 @@ impl TypeParam { | |||
1392 | pub fn ty(self, db: &dyn HirDatabase) -> Type { | 1441 | pub fn ty(self, db: &dyn HirDatabase) -> Type { |
1393 | let resolver = self.id.parent.resolver(db.upcast()); | 1442 | let resolver = self.id.parent.resolver(db.upcast()); |
1394 | let krate = self.id.parent.module(db.upcast()).krate(); | 1443 | let krate = self.id.parent.module(db.upcast()).krate(); |
1395 | let ty = Ty::Placeholder(self.id); | 1444 | let ty = TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id)).intern(&Interner); |
1396 | Type::new_with_resolver_inner(db, krate, &resolver, ty) | 1445 | Type::new_with_resolver_inner(db, krate, &resolver, ty) |
1397 | } | 1446 | } |
1398 | 1447 | ||
@@ -1420,19 +1469,6 @@ impl TypeParam { | |||
1420 | } | 1469 | } |
1421 | } | 1470 | } |
1422 | 1471 | ||
1423 | impl HirDisplay for TypeParam { | ||
1424 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
1425 | write!(f, "{}", self.name(f.db))?; | ||
1426 | let bounds = f.db.generic_predicates_for_param(self.id); | ||
1427 | let substs = Substs::type_params(f.db, self.id.parent); | ||
1428 | let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>(); | ||
1429 | if !(predicates.is_empty() || f.omit_verbose_types()) { | ||
1430 | write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?; | ||
1431 | } | ||
1432 | Ok(()) | ||
1433 | } | ||
1434 | } | ||
1435 | |||
1436 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 1472 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
1437 | pub struct LifetimeParam { | 1473 | pub struct LifetimeParam { |
1438 | pub(crate) id: LifetimeParamId, | 1474 | pub(crate) id: LifetimeParamId, |
@@ -1491,9 +1527,44 @@ impl Impl { | |||
1491 | 1527 | ||
1492 | inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect() | 1528 | inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect() |
1493 | } | 1529 | } |
1494 | pub fn for_trait(db: &dyn HirDatabase, krate: Crate, trait_: Trait) -> Vec<Impl> { | 1530 | |
1495 | let impls = db.trait_impls_in_crate(krate.id); | 1531 | pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty }: Type) -> Vec<Impl> { |
1496 | impls.for_trait(trait_.id).map(Self::from).collect() | 1532 | let def_crates = match ty.value.def_crates(db, krate) { |
1533 | Some(def_crates) => def_crates, | ||
1534 | None => return Vec::new(), | ||
1535 | }; | ||
1536 | |||
1537 | let filter = |impl_def: &Impl| { | ||
1538 | let target_ty = impl_def.target_ty(db); | ||
1539 | let rref = target_ty.remove_ref(); | ||
1540 | ty.value.equals_ctor(rref.as_ref().map_or(&target_ty.ty.value, |it| &it.ty.value)) | ||
1541 | }; | ||
1542 | |||
1543 | let mut all = Vec::new(); | ||
1544 | def_crates.into_iter().for_each(|id| { | ||
1545 | all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter)) | ||
1546 | }); | ||
1547 | let fp = TyFingerprint::for_impl(&ty.value); | ||
1548 | for id in db.crate_graph().iter() { | ||
1549 | match fp { | ||
1550 | Some(fp) => all.extend( | ||
1551 | db.trait_impls_in_crate(id).for_self_ty(fp).map(Self::from).filter(filter), | ||
1552 | ), | ||
1553 | None => all | ||
1554 | .extend(db.trait_impls_in_crate(id).all_impls().map(Self::from).filter(filter)), | ||
1555 | } | ||
1556 | } | ||
1557 | all | ||
1558 | } | ||
1559 | |||
1560 | pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> { | ||
1561 | let krate = trait_.module(db).krate(); | ||
1562 | let mut all = Vec::new(); | ||
1563 | for Crate { id } in krate.reverse_dependencies(db).into_iter().chain(Some(krate)) { | ||
1564 | let impls = db.trait_impls_in_crate(id); | ||
1565 | all.extend(impls.for_trait(trait_.id).map(Self::from)) | ||
1566 | } | ||
1567 | all | ||
1497 | } | 1568 | } |
1498 | 1569 | ||
1499 | // FIXME: the return type is wrong. This should be a hir version of | 1570 | // FIXME: the return type is wrong. This should be a hir version of |
@@ -1507,7 +1578,7 @@ impl Impl { | |||
1507 | let resolver = self.id.resolver(db.upcast()); | 1578 | let resolver = self.id.resolver(db.upcast()); |
1508 | let krate = self.id.lookup(db.upcast()).container.krate(); | 1579 | let krate = self.id.lookup(db.upcast()).container.krate(); |
1509 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); | 1580 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); |
1510 | let ty = Ty::from_hir(&ctx, &impl_data.target_type); | 1581 | let ty = ctx.lower_ty(&impl_data.target_type); |
1511 | Type::new_with_resolver_inner(db, krate, &resolver, ty) | 1582 | Type::new_with_resolver_inner(db, krate, &resolver, ty) |
1512 | } | 1583 | } |
1513 | 1584 | ||
@@ -1571,13 +1642,15 @@ impl Type { | |||
1571 | resolver: &Resolver, | 1642 | resolver: &Resolver, |
1572 | ty: Ty, | 1643 | ty: Ty, |
1573 | ) -> Type { | 1644 | ) -> Type { |
1574 | let environment = TraitEnvironment::lower(db, &resolver); | 1645 | let environment = |
1646 | resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d)); | ||
1575 | Type { krate, ty: InEnvironment { value: ty, environment } } | 1647 | Type { krate, ty: InEnvironment { value: ty, environment } } |
1576 | } | 1648 | } |
1577 | 1649 | ||
1578 | fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type { | 1650 | fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type { |
1579 | let resolver = lexical_env.resolver(db.upcast()); | 1651 | let resolver = lexical_env.resolver(db.upcast()); |
1580 | let environment = TraitEnvironment::lower(db, &resolver); | 1652 | let environment = |
1653 | resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d)); | ||
1581 | Type { krate, ty: InEnvironment { value: ty, environment } } | 1654 | Type { krate, ty: InEnvironment { value: ty, environment } } |
1582 | } | 1655 | } |
1583 | 1656 | ||
@@ -1592,25 +1665,29 @@ impl Type { | |||
1592 | } | 1665 | } |
1593 | 1666 | ||
1594 | pub fn is_unit(&self) -> bool { | 1667 | pub fn is_unit(&self) -> bool { |
1595 | matches!(self.ty.value, Ty::Tuple(0, ..)) | 1668 | matches!(self.ty.value.interned(&Interner), TyKind::Tuple(0, ..)) |
1596 | } | 1669 | } |
1597 | pub fn is_bool(&self) -> bool { | 1670 | pub fn is_bool(&self) -> bool { |
1598 | matches!(self.ty.value, Ty::Scalar(Scalar::Bool)) | 1671 | matches!(self.ty.value.interned(&Interner), TyKind::Scalar(Scalar::Bool)) |
1599 | } | 1672 | } |
1600 | 1673 | ||
1601 | pub fn is_mutable_reference(&self) -> bool { | 1674 | pub fn is_mutable_reference(&self) -> bool { |
1602 | matches!(self.ty.value, Ty::Ref(hir_ty::Mutability::Mut, ..)) | 1675 | matches!(self.ty.value.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) |
1676 | } | ||
1677 | |||
1678 | pub fn is_usize(&self) -> bool { | ||
1679 | matches!(self.ty.value.interned(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize))) | ||
1603 | } | 1680 | } |
1604 | 1681 | ||
1605 | pub fn remove_ref(&self) -> Option<Type> { | 1682 | pub fn remove_ref(&self) -> Option<Type> { |
1606 | match &self.ty.value { | 1683 | match &self.ty.value.interned(&Interner) { |
1607 | Ty::Ref(.., substs) => Some(self.derived(substs[0].clone())), | 1684 | TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), |
1608 | _ => None, | 1685 | _ => None, |
1609 | } | 1686 | } |
1610 | } | 1687 | } |
1611 | 1688 | ||
1612 | pub fn is_unknown(&self) -> bool { | 1689 | pub fn is_unknown(&self) -> bool { |
1613 | matches!(self.ty.value, Ty::Unknown) | 1690 | self.ty.value.is_unknown() |
1614 | } | 1691 | } |
1615 | 1692 | ||
1616 | /// Checks that particular type `ty` implements `std::future::Future`. | 1693 | /// Checks that particular type `ty` implements `std::future::Future`. |
@@ -1691,8 +1768,11 @@ impl Type { | |||
1691 | .fill(args.iter().map(|t| t.ty.value.clone())) | 1768 | .fill(args.iter().map(|t| t.ty.value.clone())) |
1692 | .build(); | 1769 | .build(); |
1693 | let predicate = ProjectionPredicate { | 1770 | let predicate = ProjectionPredicate { |
1694 | projection_ty: ProjectionTy { associated_ty: alias.id, parameters: subst }, | 1771 | projection_ty: ProjectionTy { |
1695 | ty: Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)), | 1772 | associated_ty_id: to_assoc_type_id(alias.id), |
1773 | substitution: subst, | ||
1774 | }, | ||
1775 | ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner), | ||
1696 | }; | 1776 | }; |
1697 | let goal = Canonical { | 1777 | let goal = Canonical { |
1698 | value: InEnvironment::new( | 1778 | value: InEnvironment::new( |
@@ -1720,26 +1800,23 @@ impl Type { | |||
1720 | } | 1800 | } |
1721 | 1801 | ||
1722 | pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { | 1802 | pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { |
1723 | let def = match self.ty.value { | 1803 | let def = self.ty.value.callable_def(db); |
1724 | Ty::FnDef(def, _) => Some(def), | ||
1725 | _ => None, | ||
1726 | }; | ||
1727 | 1804 | ||
1728 | let sig = self.ty.value.callable_sig(db)?; | 1805 | let sig = self.ty.value.callable_sig(db)?; |
1729 | Some(Callable { ty: self.clone(), sig, def, is_bound_method: false }) | 1806 | Some(Callable { ty: self.clone(), sig, def, is_bound_method: false }) |
1730 | } | 1807 | } |
1731 | 1808 | ||
1732 | pub fn is_closure(&self) -> bool { | 1809 | pub fn is_closure(&self) -> bool { |
1733 | matches!(&self.ty.value, Ty::Closure { .. }) | 1810 | matches!(&self.ty.value.interned(&Interner), TyKind::Closure { .. }) |
1734 | } | 1811 | } |
1735 | 1812 | ||
1736 | pub fn is_fn(&self) -> bool { | 1813 | pub fn is_fn(&self) -> bool { |
1737 | matches!(&self.ty.value, Ty::FnDef(..) | Ty::Function { .. }) | 1814 | matches!(&self.ty.value.interned(&Interner), TyKind::FnDef(..) | TyKind::Function { .. }) |
1738 | } | 1815 | } |
1739 | 1816 | ||
1740 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { | 1817 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { |
1741 | let adt_id = match self.ty.value { | 1818 | let adt_id = match self.ty.value.interned(&Interner) { |
1742 | Ty::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, | 1819 | &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, |
1743 | _ => return false, | 1820 | _ => return false, |
1744 | }; | 1821 | }; |
1745 | 1822 | ||
@@ -1751,24 +1828,45 @@ impl Type { | |||
1751 | } | 1828 | } |
1752 | 1829 | ||
1753 | pub fn is_raw_ptr(&self) -> bool { | 1830 | pub fn is_raw_ptr(&self) -> bool { |
1754 | matches!(&self.ty.value, Ty::Raw(..)) | 1831 | matches!(&self.ty.value.interned(&Interner), TyKind::Raw(..)) |
1755 | } | 1832 | } |
1756 | 1833 | ||
1757 | pub fn contains_unknown(&self) -> bool { | 1834 | pub fn contains_unknown(&self) -> bool { |
1758 | return go(&self.ty.value); | 1835 | return go(&self.ty.value); |
1759 | 1836 | ||
1760 | fn go(ty: &Ty) -> bool { | 1837 | fn go(ty: &Ty) -> bool { |
1761 | match ty { | 1838 | match ty.interned(&Interner) { |
1762 | Ty::Unknown => true, | 1839 | TyKind::Unknown => true, |
1763 | _ => ty.substs().map_or(false, |substs| substs.iter().any(go)), | 1840 | |
1841 | TyKind::Adt(_, substs) | ||
1842 | | TyKind::AssociatedType(_, substs) | ||
1843 | | TyKind::Tuple(_, substs) | ||
1844 | | TyKind::OpaqueType(_, substs) | ||
1845 | | TyKind::FnDef(_, substs) | ||
1846 | | TyKind::Closure(_, substs) => substs.iter().any(go), | ||
1847 | |||
1848 | TyKind::Array(ty) | TyKind::Slice(ty) | TyKind::Raw(_, ty) | TyKind::Ref(_, ty) => { | ||
1849 | go(ty) | ||
1850 | } | ||
1851 | |||
1852 | TyKind::Scalar(_) | ||
1853 | | TyKind::Str | ||
1854 | | TyKind::Never | ||
1855 | | TyKind::Placeholder(_) | ||
1856 | | TyKind::BoundVar(_) | ||
1857 | | TyKind::InferenceVar(_, _) | ||
1858 | | TyKind::Dyn(_) | ||
1859 | | TyKind::Function(_) | ||
1860 | | TyKind::Alias(_) | ||
1861 | | TyKind::ForeignType(_) => false, | ||
1764 | } | 1862 | } |
1765 | } | 1863 | } |
1766 | } | 1864 | } |
1767 | 1865 | ||
1768 | pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { | 1866 | pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { |
1769 | let (variant_id, substs) = match self.ty.value { | 1867 | let (variant_id, substs) = match self.ty.value.interned(&Interner) { |
1770 | Ty::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), | 1868 | &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), |
1771 | Ty::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), | 1869 | &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), |
1772 | _ => return Vec::new(), | 1870 | _ => return Vec::new(), |
1773 | }; | 1871 | }; |
1774 | 1872 | ||
@@ -1783,7 +1881,7 @@ impl Type { | |||
1783 | } | 1881 | } |
1784 | 1882 | ||
1785 | pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { | 1883 | pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { |
1786 | if let Ty::Tuple(_, substs) = &self.ty.value { | 1884 | if let TyKind::Tuple(_, substs) = &self.ty.value.interned(&Interner) { |
1787 | substs.iter().map(|ty| self.derived(ty.clone())).collect() | 1885 | substs.iter().map(|ty| self.derived(ty.clone())).collect() |
1788 | } else { | 1886 | } else { |
1789 | Vec::new() | 1887 | Vec::new() |
@@ -1918,12 +2016,6 @@ impl Type { | |||
1918 | self.ty.value.associated_type_parent_trait(db).map(Into::into) | 2016 | self.ty.value.associated_type_parent_trait(db).map(Into::into) |
1919 | } | 2017 | } |
1920 | 2018 | ||
1921 | // FIXME: provide required accessors such that it becomes implementable from outside. | ||
1922 | pub fn is_equal_for_find_impls(&self, other: &Type) -> bool { | ||
1923 | let rref = other.remove_ref(); | ||
1924 | self.ty.value.equals_ctor(rref.as_ref().map_or(&other.ty.value, |it| &it.ty.value)) | ||
1925 | } | ||
1926 | |||
1927 | fn derived(&self, ty: Ty) -> Type { | 2019 | fn derived(&self, ty: Ty) -> Type { |
1928 | Type { | 2020 | Type { |
1929 | krate: self.krate, | 2021 | krate: self.krate, |
@@ -1965,36 +2057,40 @@ impl Type { | |||
1965 | 2057 | ||
1966 | fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { | 2058 | fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { |
1967 | let ty = type_.ty.value.strip_references(); | 2059 | let ty = type_.ty.value.strip_references(); |
1968 | match ty { | 2060 | match ty.interned(&Interner) { |
1969 | Ty::Adt(..) => { | 2061 | TyKind::Adt(..) => { |
1970 | cb(type_.derived(ty.clone())); | 2062 | cb(type_.derived(ty.clone())); |
1971 | } | 2063 | } |
1972 | Ty::AssociatedType(..) => { | 2064 | TyKind::AssociatedType(..) => { |
1973 | if let Some(_) = ty.associated_type_parent_trait(db) { | 2065 | if let Some(_) = ty.associated_type_parent_trait(db) { |
1974 | cb(type_.derived(ty.clone())); | 2066 | cb(type_.derived(ty.clone())); |
1975 | } | 2067 | } |
1976 | } | 2068 | } |
1977 | Ty::OpaqueType(..) => { | 2069 | TyKind::OpaqueType(..) => { |
1978 | if let Some(bounds) = ty.impl_trait_bounds(db) { | 2070 | if let Some(bounds) = ty.impl_trait_bounds(db) { |
1979 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | 2071 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); |
1980 | } | 2072 | } |
1981 | } | 2073 | } |
1982 | Ty::Alias(AliasTy::Opaque(opaque_ty)) => { | 2074 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { |
1983 | if let Some(bounds) = ty.impl_trait_bounds(db) { | 2075 | if let Some(bounds) = ty.impl_trait_bounds(db) { |
1984 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | 2076 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); |
1985 | } | 2077 | } |
1986 | 2078 | ||
1987 | walk_substs(db, type_, &opaque_ty.parameters, cb); | 2079 | walk_substs(db, type_, &opaque_ty.substitution, cb); |
1988 | } | 2080 | } |
1989 | Ty::Placeholder(_) => { | 2081 | TyKind::Placeholder(_) => { |
1990 | if let Some(bounds) = ty.impl_trait_bounds(db) { | 2082 | if let Some(bounds) = ty.impl_trait_bounds(db) { |
1991 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | 2083 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); |
1992 | } | 2084 | } |
1993 | } | 2085 | } |
1994 | Ty::Dyn(bounds) => { | 2086 | TyKind::Dyn(bounds) => { |
1995 | walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); | 2087 | walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); |
1996 | } | 2088 | } |
1997 | 2089 | ||
2090 | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) | TyKind::Array(ty) | TyKind::Slice(ty) => { | ||
2091 | walk_type(db, &type_.derived(ty.clone()), cb); | ||
2092 | } | ||
2093 | |||
1998 | _ => {} | 2094 | _ => {} |
1999 | } | 2095 | } |
2000 | if let Some(substs) = ty.substs() { | 2096 | if let Some(substs) = ty.substs() { |
@@ -2006,12 +2102,6 @@ impl Type { | |||
2006 | } | 2102 | } |
2007 | } | 2103 | } |
2008 | 2104 | ||
2009 | impl HirDisplay for Type { | ||
2010 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
2011 | self.ty.value.hir_fmt(f) | ||
2012 | } | ||
2013 | } | ||
2014 | |||
2015 | // FIXME: closures | 2105 | // FIXME: closures |
2016 | #[derive(Debug)] | 2106 | #[derive(Debug)] |
2017 | pub struct Callable { | 2107 | pub struct Callable { |
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 945638cc5..519339c0c 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs | |||
@@ -259,6 +259,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
259 | } | 259 | } |
260 | 260 | ||
261 | pub fn to_module_def(&self, file: FileId) -> Option<Module> { | 261 | pub fn to_module_def(&self, file: FileId) -> Option<Module> { |
262 | self.imp.to_module_def(file).next() | ||
263 | } | ||
264 | |||
265 | pub fn to_module_defs(&self, file: FileId) -> impl Iterator<Item = Module> { | ||
262 | self.imp.to_module_def(file) | 266 | self.imp.to_module_def(file) |
263 | } | 267 | } |
264 | 268 | ||
@@ -537,8 +541,8 @@ impl<'db> SemanticsImpl<'db> { | |||
537 | f(&mut ctx) | 541 | f(&mut ctx) |
538 | } | 542 | } |
539 | 543 | ||
540 | fn to_module_def(&self, file: FileId) -> Option<Module> { | 544 | fn to_module_def(&self, file: FileId) -> impl Iterator<Item = Module> { |
541 | self.with_ctx(|ctx| ctx.file_to_def(file)).map(Module::from) | 545 | self.with_ctx(|ctx| ctx.file_to_def(file)).into_iter().map(Module::from) |
542 | } | 546 | } |
543 | 547 | ||
544 | fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> { | 548 | fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> { |
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index 6c612ee86..e9d820140 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs | |||
@@ -12,6 +12,7 @@ use hir_def::{ | |||
12 | }; | 12 | }; |
13 | use hir_expand::{name::AsName, AstId, MacroDefKind}; | 13 | use hir_expand::{name::AsName, AstId, MacroDefKind}; |
14 | use rustc_hash::FxHashMap; | 14 | use rustc_hash::FxHashMap; |
15 | use smallvec::SmallVec; | ||
15 | use stdx::impl_from; | 16 | use stdx::impl_from; |
16 | use syntax::{ | 17 | use syntax::{ |
17 | ast::{self, NameOwner}, | 18 | ast::{self, NameOwner}, |
@@ -28,14 +29,19 @@ pub(super) struct SourceToDefCtx<'a, 'b> { | |||
28 | } | 29 | } |
29 | 30 | ||
30 | impl SourceToDefCtx<'_, '_> { | 31 | impl SourceToDefCtx<'_, '_> { |
31 | pub(super) fn file_to_def(&mut self, file: FileId) -> Option<ModuleId> { | 32 | pub(super) fn file_to_def(&mut self, file: FileId) -> SmallVec<[ModuleId; 1]> { |
32 | let _p = profile::span("SourceBinder::to_module_def"); | 33 | let _p = profile::span("SourceBinder::to_module_def"); |
33 | self.db.relevant_crates(file).iter().find_map(|&crate_id| { | 34 | let mut mods = SmallVec::new(); |
35 | for &crate_id in self.db.relevant_crates(file).iter() { | ||
34 | // FIXME: inner items | 36 | // FIXME: inner items |
35 | let crate_def_map = self.db.crate_def_map(crate_id); | 37 | let crate_def_map = self.db.crate_def_map(crate_id); |
36 | let local_id = crate_def_map.modules_for_file(file).next()?; | 38 | mods.extend( |
37 | Some(crate_def_map.module_id(local_id)) | 39 | crate_def_map |
38 | }) | 40 | .modules_for_file(file) |
41 | .map(|local_id| crate_def_map.module_id(local_id)), | ||
42 | ) | ||
43 | } | ||
44 | mods | ||
39 | } | 45 | } |
40 | 46 | ||
41 | pub(super) fn module_to_def(&mut self, src: InFile<ast::Module>) -> Option<ModuleId> { | 47 | pub(super) fn module_to_def(&mut self, src: InFile<ast::Module>) -> Option<ModuleId> { |
@@ -55,7 +61,7 @@ impl SourceToDefCtx<'_, '_> { | |||
55 | Some(parent_declaration) => self.module_to_def(parent_declaration), | 61 | Some(parent_declaration) => self.module_to_def(parent_declaration), |
56 | None => { | 62 | None => { |
57 | let file_id = src.file_id.original_file(self.db.upcast()); | 63 | let file_id = src.file_id.original_file(self.db.upcast()); |
58 | self.file_to_def(file_id) | 64 | self.file_to_def(file_id).get(0).copied() |
59 | } | 65 | } |
60 | }?; | 66 | }?; |
61 | 67 | ||
@@ -185,7 +191,7 @@ impl SourceToDefCtx<'_, '_> { | |||
185 | ) -> Option<MacroDefId> { | 191 | ) -> Option<MacroDefId> { |
186 | let kind = MacroDefKind::Declarative; | 192 | let kind = MacroDefKind::Declarative; |
187 | let file_id = src.file_id.original_file(self.db.upcast()); | 193 | let file_id = src.file_id.original_file(self.db.upcast()); |
188 | let krate = self.file_to_def(file_id)?.krate(); | 194 | let krate = self.file_to_def(file_id).get(0).copied()?.krate(); |
189 | let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value); | 195 | let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value); |
190 | let ast_id = Some(AstId::new(src.file_id, file_ast_id.upcast())); | 196 | let ast_id = Some(AstId::new(src.file_id, file_ast_id.upcast())); |
191 | Some(MacroDefId { krate, ast_id, kind, local_inner: false }) | 197 | Some(MacroDefId { krate, ast_id, kind, local_inner: false }) |
@@ -245,7 +251,7 @@ impl SourceToDefCtx<'_, '_> { | |||
245 | return Some(res); | 251 | return Some(res); |
246 | } | 252 | } |
247 | 253 | ||
248 | let def = self.file_to_def(src.file_id.original_file(self.db.upcast()))?; | 254 | let def = self.file_to_def(src.file_id.original_file(self.db.upcast())).get(0).copied()?; |
249 | Some(def.into()) | 255 | Some(def.into()) |
250 | } | 256 | } |
251 | 257 | ||
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index d546512cb..4d59293e9 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs | |||
@@ -161,8 +161,9 @@ impl SourceAnalyzer { | |||
161 | db: &dyn HirDatabase, | 161 | db: &dyn HirDatabase, |
162 | field: &ast::RecordExprField, | 162 | field: &ast::RecordExprField, |
163 | ) -> Option<(Field, Option<Local>)> { | 163 | ) -> Option<(Field, Option<Local>)> { |
164 | let expr = field.expr()?; | 164 | let expr_id = |
165 | let expr_id = self.expr_id(db, &expr)?; | 165 | self.body_source_map.as_ref()?.node_field(InFile::new(self.file_id, field))?; |
166 | |||
166 | let local = if field.name_ref().is_some() { | 167 | let local = if field.name_ref().is_some() { |
167 | None | 168 | None |
168 | } else { | 169 | } else { |