aboutsummaryrefslogtreecommitdiff
path: root/crates/hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir/src')
-rw-r--r--crates/hir/src/display.rs467
-rw-r--r--crates/hir/src/lib.rs129
-rw-r--r--crates/hir/src/semantics.rs30
-rw-r--r--crates/hir/src/source_analyzer.rs4
4 files changed, 586 insertions, 44 deletions
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
new file mode 100644
index 000000000..9f6d7be48
--- /dev/null
+++ b/crates/hir/src/display.rs
@@ -0,0 +1,467 @@
1//! HirDisplay implementations for various hir types.
2use hir_def::{
3 adt::VariantData,
4 generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget},
5 type_ref::{TypeBound, TypeRef},
6 AdtId, GenericDefId,
7};
8use hir_ty::display::{
9 write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError,
10 HirFormatter,
11};
12use syntax::ast::{self, NameOwner};
13
14use crate::{
15 Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasVisibility, LifetimeParam,
16 Module, Static, Struct, Substitution, Trait, Type, TypeAlias, TypeParam, Union, Variant,
17};
18
19impl 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
123impl HirDisplay for Adt {
124 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
125 match self {
126 Adt::Struct(it) => it.hir_fmt(f),
127 Adt::Union(it) => it.hir_fmt(f),
128 Adt::Enum(it) => it.hir_fmt(f),
129 }
130 }
131}
132
133impl HirDisplay for Struct {
134 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
135 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
136 write!(f, "struct ")?;
137 write!(f, "{}", self.name(f.db))?;
138 let def_id = GenericDefId::AdtId(AdtId::StructId(self.id));
139 write_generic_params(def_id, f)?;
140 write_where_clause(def_id, f)?;
141 Ok(())
142 }
143}
144
145impl HirDisplay for Enum {
146 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
147 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
148 write!(f, "enum ")?;
149 write!(f, "{}", self.name(f.db))?;
150 let def_id = GenericDefId::AdtId(AdtId::EnumId(self.id));
151 write_generic_params(def_id, f)?;
152 write_where_clause(def_id, f)?;
153 Ok(())
154 }
155}
156
157impl HirDisplay for Union {
158 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
159 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
160 write!(f, "union ")?;
161 write!(f, "{}", self.name(f.db))?;
162 let def_id = GenericDefId::AdtId(AdtId::UnionId(self.id));
163 write_generic_params(def_id, f)?;
164 write_where_clause(def_id, f)?;
165 Ok(())
166 }
167}
168
169impl HirDisplay for Field {
170 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
171 write_visibility(self.parent.module(f.db).id, self.visibility(f.db), f)?;
172 write!(f, "{}: ", self.name(f.db))?;
173 self.signature_ty(f.db).hir_fmt(f)
174 }
175}
176
177impl HirDisplay for Variant {
178 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
179 write!(f, "{}", self.name(f.db))?;
180 let data = self.variant_data(f.db);
181 match &*data {
182 VariantData::Unit => {}
183 VariantData::Tuple(fields) => {
184 write!(f, "(")?;
185 let mut first = true;
186 for (_, field) in fields.iter() {
187 if first {
188 first = false;
189 } else {
190 write!(f, ", ")?;
191 }
192 // Enum variant fields must be pub.
193 field.type_ref.hir_fmt(f)?;
194 }
195 write!(f, ")")?;
196 }
197 VariantData::Record(fields) => {
198 write!(f, " {{")?;
199 let mut first = true;
200 for (_, field) in fields.iter() {
201 if first {
202 first = false;
203 write!(f, " ")?;
204 } else {
205 write!(f, ", ")?;
206 }
207 // Enum variant fields must be pub.
208 write!(f, "{}: ", field.name)?;
209 field.type_ref.hir_fmt(f)?;
210 }
211 write!(f, " }}")?;
212 }
213 }
214 Ok(())
215 }
216}
217
218impl HirDisplay for Type {
219 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
220 self.ty.value.hir_fmt(f)
221 }
222}
223
224impl HirDisplay for GenericParam {
225 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
226 match self {
227 GenericParam::TypeParam(it) => it.hir_fmt(f),
228 GenericParam::LifetimeParam(it) => it.hir_fmt(f),
229 GenericParam::ConstParam(it) => it.hir_fmt(f),
230 }
231 }
232}
233
234impl HirDisplay for TypeParam {
235 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
236 write!(f, "{}", self.name(f.db))?;
237 let bounds = f.db.generic_predicates_for_param(self.id);
238 let substs = Substitution::type_params(f.db, self.id.parent);
239 let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>();
240 if !(predicates.is_empty() || f.omit_verbose_types()) {
241 write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?;
242 }
243 Ok(())
244 }
245}
246
247impl HirDisplay for LifetimeParam {
248 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
249 write!(f, "{}", self.name(f.db))
250 }
251}
252
253impl HirDisplay for ConstParam {
254 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
255 write!(f, "const {}: ", self.name(f.db))?;
256 self.ty(f.db).hir_fmt(f)
257 }
258}
259
260fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
261 let params = f.db.generic_params(def);
262 if params.lifetimes.is_empty()
263 && params.consts.is_empty()
264 && params
265 .types
266 .iter()
267 .all(|(_, param)| !matches!(param.provenance, TypeParamProvenance::TypeParamList))
268 {
269 return Ok(());
270 }
271 write!(f, "<")?;
272
273 let mut first = true;
274 let mut delim = |f: &mut HirFormatter| {
275 if first {
276 first = false;
277 Ok(())
278 } else {
279 write!(f, ", ")
280 }
281 };
282 for (_, lifetime) in params.lifetimes.iter() {
283 delim(f)?;
284 write!(f, "{}", lifetime.name)?;
285 }
286 for (_, ty) in params.types.iter() {
287 if ty.provenance != TypeParamProvenance::TypeParamList {
288 continue;
289 }
290 if let Some(name) = &ty.name {
291 delim(f)?;
292 write!(f, "{}", name)?;
293 if let Some(default) = &ty.default {
294 write!(f, " = ")?;
295 default.hir_fmt(f)?;
296 }
297 }
298 }
299 for (_, konst) in params.consts.iter() {
300 delim(f)?;
301 write!(f, "const {}: ", konst.name)?;
302 konst.ty.hir_fmt(f)?;
303 }
304
305 write!(f, ">")?;
306 Ok(())
307}
308
309fn write_where_clause(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
310 let params = f.db.generic_params(def);
311 if params.where_predicates.is_empty() {
312 return Ok(());
313 }
314
315 let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter| match target {
316 WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f),
317 WherePredicateTypeTarget::TypeParam(id) => match &params.types[*id].name {
318 Some(name) => write!(f, "{}", name),
319 None => write!(f, "{{unnamed}}"),
320 },
321 };
322
323 write!(f, "\nwhere")?;
324
325 for (pred_idx, pred) in params.where_predicates.iter().enumerate() {
326 let prev_pred =
327 if pred_idx == 0 { None } else { Some(&params.where_predicates[pred_idx - 1]) };
328
329 let new_predicate = |f: &mut HirFormatter| {
330 write!(f, "{}", if pred_idx == 0 { "\n " } else { ",\n " })
331 };
332
333 match pred {
334 WherePredicate::TypeBound { target, bound } => {
335 if matches!(prev_pred, Some(WherePredicate::TypeBound { target: target_, .. }) if target_ == target)
336 {
337 write!(f, " + ")?;
338 } else {
339 new_predicate(f)?;
340 write_target(target, f)?;
341 write!(f, ": ")?;
342 }
343 bound.hir_fmt(f)?;
344 }
345 WherePredicate::Lifetime { target, bound } => {
346 if matches!(prev_pred, Some(WherePredicate::Lifetime { target: target_, .. }) if target_ == target)
347 {
348 write!(f, " + {}", bound.name)?;
349 } else {
350 new_predicate(f)?;
351 write!(f, "{}: {}", target.name, bound.name)?;
352 }
353 }
354 WherePredicate::ForLifetime { lifetimes, target, bound } => {
355 if matches!(
356 prev_pred,
357 Some(WherePredicate::ForLifetime { lifetimes: lifetimes_, target: target_, .. })
358 if lifetimes_ == lifetimes && target_ == target,
359 ) {
360 write!(f, " + ")?;
361 } else {
362 new_predicate(f)?;
363 write!(f, "for<")?;
364 for (idx, lifetime) in lifetimes.iter().enumerate() {
365 if idx != 0 {
366 write!(f, ", ")?;
367 }
368 write!(f, "{}", lifetime)?;
369 }
370 write!(f, "> ")?;
371 write_target(target, f)?;
372 write!(f, ": ")?;
373 }
374 bound.hir_fmt(f)?;
375 }
376 }
377 }
378
379 // End of final predicate. There must be at least one predicate here.
380 write!(f, ",")?;
381
382 Ok(())
383}
384
385impl HirDisplay for Const {
386 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
387 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
388 let data = f.db.const_data(self.id);
389 write!(f, "const ")?;
390 match &data.name {
391 Some(name) => write!(f, "{}: ", name)?,
392 None => write!(f, "_: ")?,
393 }
394 data.type_ref.hir_fmt(f)?;
395 Ok(())
396 }
397}
398
399impl HirDisplay for Static {
400 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
401 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
402 let data = f.db.static_data(self.id);
403 write!(f, "static ")?;
404 if data.mutable {
405 write!(f, "mut ")?;
406 }
407 match &data.name {
408 Some(name) => write!(f, "{}: ", name)?,
409 None => write!(f, "_: ")?,
410 }
411 data.type_ref.hir_fmt(f)?;
412 Ok(())
413 }
414}
415
416impl HirDisplay for Trait {
417 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
418 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
419 let data = f.db.trait_data(self.id);
420 if data.is_unsafe {
421 write!(f, "unsafe ")?;
422 }
423 if data.is_auto {
424 write!(f, "auto ")?;
425 }
426 write!(f, "trait {}", data.name)?;
427 let def_id = GenericDefId::TraitId(self.id);
428 write_generic_params(def_id, f)?;
429 if !data.bounds.is_empty() {
430 write!(f, ": ")?;
431 f.write_joined(&*data.bounds, " + ")?;
432 }
433 write_where_clause(def_id, f)?;
434 Ok(())
435 }
436}
437
438impl HirDisplay for TypeAlias {
439 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
440 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
441 let data = f.db.type_alias_data(self.id);
442 write!(f, "type {}", data.name)?;
443 if !data.bounds.is_empty() {
444 write!(f, ": ")?;
445 f.write_joined(&data.bounds, " + ")?;
446 }
447 if let Some(ty) = &data.type_ref {
448 write!(f, " = ")?;
449 ty.hir_fmt(f)?;
450 }
451 Ok(())
452 }
453}
454
455impl HirDisplay for Module {
456 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
457 // FIXME: Module doesn't have visibility saved in data.
458 match self.name(f.db) {
459 Some(name) => write!(f, "mod {}", name),
460 None if self.crate_root(f.db) == *self => match self.krate().display_name(f.db) {
461 Some(name) => write!(f, "extern crate {}", name),
462 None => write!(f, "extern crate {{unknown}}"),
463 },
464 None => write!(f, "mod {{unnamed}}"),
465 }
466 }
467}
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index c5161dadd..12dd5fb38 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -29,6 +29,8 @@ mod has_source;
29pub mod diagnostics; 29pub mod diagnostics;
30pub mod db; 30pub mod db;
31 31
32mod display;
33
32use std::{iter, sync::Arc}; 34use std::{iter, sync::Arc};
33 35
34use arrayvec::ArrayVec; 36use arrayvec::ArrayVec;
@@ -50,14 +52,15 @@ use hir_def::{
50use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; 52use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind};
51use hir_ty::{ 53use hir_ty::{
52 autoderef, 54 autoderef,
53 display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter},
54 method_resolution::{self, TyFingerprint}, 55 method_resolution::{self, TyFingerprint},
56 primitive::UintTy,
55 to_assoc_type_id, 57 to_assoc_type_id,
56 traits::{FnTrait, Solution, SolutionVariables}, 58 traits::{FnTrait, Solution, SolutionVariables},
57 AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate, 59 AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate,
58 InEnvironment, Interner, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, Ty, 60 InEnvironment, Interner, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substitution,
59 TyDefId, TyKind, TyVariableKind, 61 Ty, TyDefId, TyKind, TyVariableKind,
60}; 62};
63use itertools::Itertools;
61use rustc_hash::FxHashSet; 64use rustc_hash::FxHashSet;
62use stdx::{format_to, impl_from}; 65use stdx::{format_to, impl_from};
63use syntax::{ 66use syntax::{
@@ -139,7 +142,6 @@ impl Crate {
139 .collect() 142 .collect()
140 } 143 }
141 144
142 // FIXME: add `transitive_reverse_dependencies`.
143 pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> { 145 pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
144 let crate_graph = db.crate_graph(); 146 let crate_graph = db.crate_graph();
145 crate_graph 147 crate_graph
@@ -151,6 +153,14 @@ impl Crate {
151 .collect() 153 .collect()
152 } 154 }
153 155
156 pub fn transitive_reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
157 db.crate_graph()
158 .transitive_reverse_dependencies(self.id)
159 .into_iter()
160 .map(|id| Crate { id })
161 .collect()
162 }
163
154 pub fn root_module(self, db: &dyn HirDatabase) -> Module { 164 pub fn root_module(self, db: &dyn HirDatabase) -> Module {
155 let def_map = db.crate_def_map(self.id); 165 let def_map = db.crate_def_map(self.id);
156 Module { id: def_map.module_id(def_map.root()) } 166 Module { id: def_map.module_id(def_map.root()) }
@@ -508,7 +518,7 @@ impl Field {
508 VariantDef::Union(it) => it.id.into(), 518 VariantDef::Union(it) => it.id.into(),
509 VariantDef::Variant(it) => it.parent.id.into(), 519 VariantDef::Variant(it) => it.parent.id.into(),
510 }; 520 };
511 let substs = Substs::type_params(db, generic_def_id); 521 let substs = Substitution::type_params(db, generic_def_id);
512 let ty = db.field_types(var_id)[self.id].clone().subst(&substs); 522 let ty = db.field_types(var_id)[self.id].clone().subst(&substs);
513 Type::new(db, self.parent.module(db).id.krate(), var_id, ty) 523 Type::new(db, self.parent.module(db).id.krate(), var_id, ty)
514 } 524 }
@@ -571,6 +581,12 @@ impl Struct {
571 } 581 }
572} 582}
573 583
584impl HasVisibility for Struct {
585 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
586 db.struct_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
587 }
588}
589
574#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 590#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
575pub struct Union { 591pub struct Union {
576 pub(crate) id: UnionId, 592 pub(crate) id: UnionId,
@@ -603,6 +619,12 @@ impl Union {
603 } 619 }
604} 620}
605 621
622impl HasVisibility for Union {
623 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
624 db.union_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
625 }
626}
627
606#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 628#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
607pub struct Enum { 629pub struct Enum {
608 pub(crate) id: EnumId, 630 pub(crate) id: EnumId,
@@ -630,6 +652,12 @@ impl Enum {
630 } 652 }
631} 653}
632 654
655impl HasVisibility for Enum {
656 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
657 db.enum_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
658 }
659}
660
633#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 661#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
634pub struct Variant { 662pub struct Variant {
635 pub(crate) parent: Enum, 663 pub(crate) parent: Enum,
@@ -821,7 +849,8 @@ impl Function {
821 db.function_data(self.id) 849 db.function_data(self.id)
822 .params 850 .params
823 .iter() 851 .iter()
824 .map(|type_ref| { 852 .enumerate()
853 .map(|(idx, type_ref)| {
825 let ty = Type { 854 let ty = Type {
826 krate, 855 krate,
827 ty: InEnvironment { 856 ty: InEnvironment {
@@ -829,7 +858,7 @@ impl Function {
829 environment: environment.clone(), 858 environment: environment.clone(),
830 }, 859 },
831 }; 860 };
832 Param { ty } 861 Param { func: self, ty, idx }
833 }) 862 })
834 .collect() 863 .collect()
835 } 864 }
@@ -843,7 +872,7 @@ impl Function {
843 } 872 }
844 873
845 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { 874 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
846 db.function_data(self.id).is_unsafe 875 db.function_data(self.id).qualifier.is_unsafe
847 } 876 }
848 877
849 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { 878 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
@@ -892,6 +921,9 @@ impl From<hir_ty::Mutability> for Access {
892 921
893#[derive(Debug)] 922#[derive(Debug)]
894pub struct Param { 923pub struct Param {
924 func: Function,
925 /// The index in parameter list, including self parameter.
926 idx: usize,
895 ty: Type, 927 ty: Type,
896} 928}
897 929
@@ -899,6 +931,15 @@ impl Param {
899 pub fn ty(&self) -> &Type { 931 pub fn ty(&self) -> &Type {
900 &self.ty 932 &self.ty
901 } 933 }
934
935 pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat> {
936 let params = self.func.source(db)?.value.param_list()?;
937 if params.self_param().is_some() {
938 params.params().nth(self.idx.checked_sub(1)?)?.pat()
939 } else {
940 params.params().nth(self.idx)?.pat()
941 }
942 }
902} 943}
903 944
904#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 945#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -921,6 +962,14 @@ impl SelfParam {
921 }) 962 })
922 .unwrap_or(Access::Owned) 963 .unwrap_or(Access::Owned)
923 } 964 }
965
966 pub fn display(self, db: &dyn HirDatabase) -> &'static str {
967 match self.access(db) {
968 Access::Shared => "&self",
969 Access::Exclusive => "&mut self",
970 Access::Owned => "self",
971 }
972 }
924} 973}
925 974
926impl HasVisibility for Function { 975impl HasVisibility for Function {
@@ -948,6 +997,10 @@ impl Const {
948 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { 997 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
949 db.const_data(self.id).name.clone() 998 db.const_data(self.id).name.clone()
950 } 999 }
1000
1001 pub fn type_ref(self, db: &dyn HirDatabase) -> TypeRef {
1002 db.const_data(self.id).type_ref.clone()
1003 }
951} 1004}
952 1005
953impl HasVisibility for Const { 1006impl HasVisibility for Const {
@@ -981,6 +1034,12 @@ impl Static {
981 } 1034 }
982} 1035}
983 1036
1037impl HasVisibility for Static {
1038 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1039 db.static_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
1040 }
1041}
1042
984#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 1043#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
985pub struct Trait { 1044pub struct Trait {
986 pub(crate) id: TraitId, 1045 pub(crate) id: TraitId,
@@ -1000,7 +1059,13 @@ impl Trait {
1000 } 1059 }
1001 1060
1002 pub fn is_auto(self, db: &dyn HirDatabase) -> bool { 1061 pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
1003 db.trait_data(self.id).auto 1062 db.trait_data(self.id).is_auto
1063 }
1064}
1065
1066impl HasVisibility for Trait {
1067 fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
1068 db.trait_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
1004 } 1069 }
1005} 1070}
1006 1071
@@ -1406,25 +1471,12 @@ impl TypeParam {
1406 let resolver = self.id.parent.resolver(db.upcast()); 1471 let resolver = self.id.parent.resolver(db.upcast());
1407 let krate = self.id.parent.module(db.upcast()).krate(); 1472 let krate = self.id.parent.module(db.upcast()).krate();
1408 let ty = params.get(local_idx)?.clone(); 1473 let ty = params.get(local_idx)?.clone();
1409 let subst = Substs::type_params(db, self.id.parent); 1474 let subst = Substitution::type_params(db, self.id.parent);
1410 let ty = ty.subst(&subst.prefix(local_idx)); 1475 let ty = ty.subst(&subst.prefix(local_idx));
1411 Some(Type::new_with_resolver_inner(db, krate, &resolver, ty)) 1476 Some(Type::new_with_resolver_inner(db, krate, &resolver, ty))
1412 } 1477 }
1413} 1478}
1414 1479
1415impl HirDisplay for TypeParam {
1416 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
1417 write!(f, "{}", self.name(f.db))?;
1418 let bounds = f.db.generic_predicates_for_param(self.id);
1419 let substs = Substs::type_params(f.db, self.id.parent);
1420 let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>();
1421 if !(predicates.is_empty() || f.omit_verbose_types()) {
1422 write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?;
1423 }
1424 Ok(())
1425 }
1426}
1427
1428#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 1480#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1429pub struct LifetimeParam { 1481pub struct LifetimeParam {
1430 pub(crate) id: LifetimeParamId, 1482 pub(crate) id: LifetimeParamId,
@@ -1497,11 +1549,17 @@ impl Impl {
1497 }; 1549 };
1498 1550
1499 let mut all = Vec::new(); 1551 let mut all = Vec::new();
1500 def_crates.into_iter().for_each(|id| { 1552 def_crates.iter().for_each(|&id| {
1501 all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter)) 1553 all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter))
1502 }); 1554 });
1503 let fp = TyFingerprint::for_impl(&ty.value); 1555 let fp = TyFingerprint::for_impl(&ty.value);
1504 for id in db.crate_graph().iter() { 1556 for id in def_crates
1557 .iter()
1558 .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db))
1559 .map(|Crate { id }| id)
1560 .chain(def_crates.iter().copied())
1561 .unique()
1562 {
1505 match fp { 1563 match fp {
1506 Some(fp) => all.extend( 1564 Some(fp) => all.extend(
1507 db.trait_impls_in_crate(id).for_self_ty(fp).map(Self::from).filter(filter), 1565 db.trait_impls_in_crate(id).for_self_ty(fp).map(Self::from).filter(filter),
@@ -1516,7 +1574,8 @@ impl Impl {
1516 pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> { 1574 pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> {
1517 let krate = trait_.module(db).krate(); 1575 let krate = trait_.module(db).krate();
1518 let mut all = Vec::new(); 1576 let mut all = Vec::new();
1519 for Crate { id } in krate.reverse_dependencies(db).into_iter().chain(Some(krate)) { 1577 for Crate { id } in krate.transitive_reverse_dependencies(db).into_iter().chain(Some(krate))
1578 {
1520 let impls = db.trait_impls_in_crate(id); 1579 let impls = db.trait_impls_in_crate(id);
1521 all.extend(impls.for_trait(trait_.id).map(Self::from)) 1580 all.extend(impls.for_trait(trait_.id).map(Self::from))
1522 } 1581 }
@@ -1615,7 +1674,7 @@ impl Type {
1615 krate: CrateId, 1674 krate: CrateId,
1616 def: impl HasResolver + Into<TyDefId> + Into<GenericDefId>, 1675 def: impl HasResolver + Into<TyDefId> + Into<GenericDefId>,
1617 ) -> Type { 1676 ) -> Type {
1618 let substs = Substs::build_for_def(db, def).fill_with_unknown().build(); 1677 let substs = Substitution::build_for_def(db, def).fill_with_unknown().build();
1619 let ty = db.ty(def.into()).subst(&substs); 1678 let ty = db.ty(def.into()).subst(&substs);
1620 Type::new(db, krate, def, ty) 1679 Type::new(db, krate, def, ty)
1621 } 1680 }
@@ -1631,6 +1690,10 @@ impl Type {
1631 matches!(self.ty.value.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) 1690 matches!(self.ty.value.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
1632 } 1691 }
1633 1692
1693 pub fn is_usize(&self) -> bool {
1694 matches!(self.ty.value.interned(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)))
1695 }
1696
1634 pub fn remove_ref(&self) -> Option<Type> { 1697 pub fn remove_ref(&self) -> Option<Type> {
1635 match &self.ty.value.interned(&Interner) { 1698 match &self.ty.value.interned(&Interner) {
1636 TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), 1699 TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
@@ -1691,7 +1754,7 @@ impl Type {
1691 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { 1754 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
1692 let trait_ref = hir_ty::TraitRef { 1755 let trait_ref = hir_ty::TraitRef {
1693 trait_: trait_.id, 1756 trait_: trait_.id,
1694 substs: Substs::build_for_def(db, trait_.id) 1757 substs: Substitution::build_for_def(db, trait_.id)
1695 .push(self.ty.value.clone()) 1758 .push(self.ty.value.clone())
1696 .fill(args.iter().map(|t| t.ty.value.clone())) 1759 .fill(args.iter().map(|t| t.ty.value.clone()))
1697 .build(), 1760 .build(),
@@ -1715,7 +1778,7 @@ impl Type {
1715 args: &[Type], 1778 args: &[Type],
1716 alias: TypeAlias, 1779 alias: TypeAlias,
1717 ) -> Option<Type> { 1780 ) -> Option<Type> {
1718 let subst = Substs::build_for_def(db, trait_.id) 1781 let subst = Substitution::build_for_def(db, trait_.id)
1719 .push(self.ty.value.clone()) 1782 .push(self.ty.value.clone())
1720 .fill(args.iter().map(|t| t.ty.value.clone())) 1783 .fill(args.iter().map(|t| t.ty.value.clone()))
1721 .build(); 1784 .build();
@@ -1982,7 +2045,7 @@ impl Type {
1982 fn walk_substs( 2045 fn walk_substs(
1983 db: &dyn HirDatabase, 2046 db: &dyn HirDatabase,
1984 type_: &Type, 2047 type_: &Type,
1985 substs: &Substs, 2048 substs: &Substitution,
1986 cb: &mut impl FnMut(Type), 2049 cb: &mut impl FnMut(Type),
1987 ) { 2050 ) {
1988 for ty in substs.iter() { 2051 for ty in substs.iter() {
@@ -2054,12 +2117,6 @@ impl Type {
2054 } 2117 }
2055} 2118}
2056 2119
2057impl HirDisplay for Type {
2058 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
2059 self.ty.value.hir_fmt(f)
2060 }
2061}
2062
2063// FIXME: closures 2120// FIXME: closures
2064#[derive(Debug)] 2121#[derive(Debug)]
2065pub struct Callable { 2122pub struct Callable {
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 519339c0c..03c9371b5 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -143,6 +143,12 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
143 self.imp.diagnostics_display_range(diagnostics) 143 self.imp.diagnostics_display_range(diagnostics)
144 } 144 }
145 145
146 pub fn token_ancestors_with_macros(
147 &self,
148 token: SyntaxToken,
149 ) -> impl Iterator<Item = SyntaxNode> + '_ {
150 token.parent().into_iter().flat_map(move |it| self.ancestors_with_macros(it))
151 }
146 pub fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ { 152 pub fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ {
147 self.imp.ancestors_with_macros(node) 153 self.imp.ancestors_with_macros(node)
148 } 154 }
@@ -270,8 +276,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
270 self.imp.scope(node) 276 self.imp.scope(node)
271 } 277 }
272 278
273 pub fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> { 279 pub fn scope_at_offset(&self, token: &SyntaxToken, offset: TextSize) -> SemanticsScope<'db> {
274 self.imp.scope_at_offset(node, offset) 280 self.imp.scope_at_offset(&token.parent().unwrap(), offset)
275 } 281 }
276 282
277 pub fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> { 283 pub fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> {
@@ -341,7 +347,10 @@ impl<'db> SemanticsImpl<'db> {
341 347
342 fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken { 348 fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken {
343 let _p = profile::span("descend_into_macros"); 349 let _p = profile::span("descend_into_macros");
344 let parent = token.parent(); 350 let parent = match token.parent() {
351 Some(it) => it,
352 None => return token,
353 };
345 let sa = self.analyze(&parent); 354 let sa = self.analyze(&parent);
346 355
347 let token = successors(Some(InFile::new(sa.file_id, token)), |token| { 356 let token = successors(Some(InFile::new(sa.file_id, token)), |token| {
@@ -360,7 +369,9 @@ impl<'db> SemanticsImpl<'db> {
360 .as_ref()? 369 .as_ref()?
361 .map_token_down(token.as_ref())?; 370 .map_token_down(token.as_ref())?;
362 371
363 self.cache(find_root(&token.value.parent()), token.file_id); 372 if let Some(parent) = token.value.parent() {
373 self.cache(find_root(&parent), token.file_id);
374 }
364 375
365 Some(token) 376 Some(token)
366 }) 377 })
@@ -378,7 +389,7 @@ impl<'db> SemanticsImpl<'db> {
378 // Handle macro token cases 389 // Handle macro token cases
379 node.token_at_offset(offset) 390 node.token_at_offset(offset)
380 .map(|token| self.descend_into_macros(token)) 391 .map(|token| self.descend_into_macros(token))
381 .map(|it| self.ancestors_with_macros(it.parent())) 392 .map(|it| self.token_ancestors_with_macros(it))
382 .flatten() 393 .flatten()
383 } 394 }
384 395
@@ -394,6 +405,13 @@ impl<'db> SemanticsImpl<'db> {
394 src.with_value(&node).original_file_range(self.db.upcast()) 405 src.with_value(&node).original_file_range(self.db.upcast())
395 } 406 }
396 407
408 fn token_ancestors_with_macros(
409 &self,
410 token: SyntaxToken,
411 ) -> impl Iterator<Item = SyntaxNode> + '_ {
412 token.parent().into_iter().flat_map(move |parent| self.ancestors_with_macros(parent))
413 }
414
397 fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ { 415 fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ {
398 let node = self.find_file(node); 416 let node = self.find_file(node);
399 node.ancestors_with_macros(self.db.upcast()).map(|it| it.value) 417 node.ancestors_with_macros(self.db.upcast()).map(|it| it.value)
@@ -405,7 +423,7 @@ impl<'db> SemanticsImpl<'db> {
405 offset: TextSize, 423 offset: TextSize,
406 ) -> impl Iterator<Item = SyntaxNode> + '_ { 424 ) -> impl Iterator<Item = SyntaxNode> + '_ {
407 node.token_at_offset(offset) 425 node.token_at_offset(offset)
408 .map(|token| self.ancestors_with_macros(token.parent())) 426 .map(|token| self.token_ancestors_with_macros(token))
409 .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) 427 .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len())
410 } 428 }
411 429
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 4d59293e9..117f32a9e 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -20,7 +20,7 @@ use hir_def::{
20use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; 20use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
21use hir_ty::{ 21use hir_ty::{
22 diagnostics::{record_literal_missing_fields, record_pattern_missing_fields}, 22 diagnostics::{record_literal_missing_fields, record_pattern_missing_fields},
23 InferenceResult, Substs, 23 InferenceResult, Substitution,
24}; 24};
25use syntax::{ 25use syntax::{
26 ast::{self, AstNode}, 26 ast::{self, AstNode},
@@ -329,7 +329,7 @@ impl SourceAnalyzer {
329 &self, 329 &self,
330 db: &dyn HirDatabase, 330 db: &dyn HirDatabase,
331 krate: CrateId, 331 krate: CrateId,
332 substs: &Substs, 332 substs: &Substitution,
333 variant: VariantId, 333 variant: VariantId,
334 missing_fields: Vec<LocalFieldId>, 334 missing_fields: Vec<LocalFieldId>,
335 ) -> Vec<(Field, Type)> { 335 ) -> Vec<(Field, Type)> {