]> git.lizzy.rs Git - rust.git/blob - crates/hir/src/display.rs
Use `FileAstId<ast::Adt>` in nameres where appropriate instead
[rust.git] / crates / hir / src / display.rs
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::{
9     display::{
10         write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError,
11         HirFormatter, SizedByDefault,
12     },
13     Interner, TraitRefExt, WhereClause,
14 };
15 use syntax::SmolStr;
16
17 use crate::{
18     Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasCrate, HasVisibility,
19     LifetimeParam, Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeParam, Union,
20     Variant,
21 };
22
23 impl HirDisplay for Function {
24     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
25         let data = f.db.function_data(self.id);
26         write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
27         if data.is_default() {
28             write!(f, "default ")?;
29         }
30         if data.is_const() {
31             write!(f, "const ")?;
32         }
33         if data.is_async() {
34             write!(f, "async ")?;
35         }
36         if data.is_unsafe() {
37             write!(f, "unsafe ")?;
38         }
39         if let Some(abi) = &data.abi {
40             // FIXME: String escape?
41             write!(f, "extern \"{}\" ", &**abi)?;
42         }
43         write!(f, "fn {}", data.name)?;
44
45         write_generic_params(GenericDefId::FunctionId(self.id), f)?;
46
47         write!(f, "(")?;
48
49         let write_self_param = |ty: &TypeRef, f: &mut HirFormatter| match ty {
50             TypeRef::Path(p) if p.is_self_type() => write!(f, "self"),
51             TypeRef::Reference(inner, lifetime, mut_) if matches!(&**inner,TypeRef::Path(p) if p.is_self_type()) =>
52             {
53                 write!(f, "&")?;
54                 if let Some(lifetime) = lifetime {
55                     write!(f, "{} ", lifetime.name)?;
56                 }
57                 if let hir_def::type_ref::Mutability::Mut = mut_ {
58                     write!(f, "mut ")?;
59                 }
60                 write!(f, "self")
61             }
62             _ => {
63                 write!(f, "self: ")?;
64                 ty.hir_fmt(f)
65             }
66         };
67
68         let mut first = true;
69         for (name, type_ref) in &data.params {
70             if !first {
71                 write!(f, ", ")?;
72             } else {
73                 first = false;
74                 if data.has_self_param() {
75                     write_self_param(type_ref, f)?;
76                     continue;
77                 }
78             }
79             match name {
80                 Some(name) => write!(f, "{}: ", name)?,
81                 None => write!(f, "_: ")?,
82             }
83             // FIXME: Use resolved `param.ty` or raw `type_ref`?
84             // The former will ignore lifetime arguments currently.
85             type_ref.hir_fmt(f)?;
86         }
87         write!(f, ")")?;
88
89         // `FunctionData::ret_type` will be `::core::future::Future<Output = ...>` for async fns.
90         // Use ugly pattern match to strip the Future trait.
91         // Better way?
92         let ret_type = if !data.is_async() {
93             &data.ret_type
94         } else {
95             match &*data.ret_type {
96                 TypeRef::ImplTrait(bounds) => match bounds[0].as_ref() {
97                     TypeBound::Path(path, _) => {
98                         path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings
99                             [0]
100                         .type_ref
101                         .as_ref()
102                         .unwrap()
103                     }
104                     _ => panic!("Async fn ret_type should be impl Future"),
105                 },
106                 _ => panic!("Async fn ret_type should be impl Future"),
107             }
108         };
109
110         match ret_type {
111             TypeRef::Tuple(tup) if tup.is_empty() => {}
112             ty => {
113                 write!(f, " -> ")?;
114                 ty.hir_fmt(f)?;
115             }
116         }
117
118         write_where_clause(GenericDefId::FunctionId(self.id), f)?;
119
120         Ok(())
121     }
122 }
123
124 impl HirDisplay for Adt {
125     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
126         match self {
127             Adt::Struct(it) => it.hir_fmt(f),
128             Adt::Union(it) => it.hir_fmt(f),
129             Adt::Enum(it) => it.hir_fmt(f),
130         }
131     }
132 }
133
134 impl HirDisplay for Struct {
135     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
136         write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
137         write!(f, "struct ")?;
138         write!(f, "{}", self.name(f.db))?;
139         let def_id = GenericDefId::AdtId(AdtId::StructId(self.id));
140         write_generic_params(def_id, f)?;
141         write_where_clause(def_id, f)?;
142         Ok(())
143     }
144 }
145
146 impl HirDisplay for Enum {
147     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
148         write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
149         write!(f, "enum ")?;
150         write!(f, "{}", self.name(f.db))?;
151         let def_id = GenericDefId::AdtId(AdtId::EnumId(self.id));
152         write_generic_params(def_id, f)?;
153         write_where_clause(def_id, f)?;
154         Ok(())
155     }
156 }
157
158 impl HirDisplay for Union {
159     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
160         write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
161         write!(f, "union ")?;
162         write!(f, "{}", self.name(f.db))?;
163         let def_id = GenericDefId::AdtId(AdtId::UnionId(self.id));
164         write_generic_params(def_id, f)?;
165         write_where_clause(def_id, f)?;
166         Ok(())
167     }
168 }
169
170 impl HirDisplay for Field {
171     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
172         write_visibility(self.parent.module(f.db).id, self.visibility(f.db), f)?;
173         write!(f, "{}: ", self.name(f.db))?;
174         self.ty(f.db).hir_fmt(f)
175     }
176 }
177
178 impl HirDisplay for Variant {
179     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
180         write!(f, "{}", self.name(f.db))?;
181         let data = self.variant_data(f.db);
182         match &*data {
183             VariantData::Unit => {}
184             VariantData::Tuple(fields) => {
185                 write!(f, "(")?;
186                 let mut first = true;
187                 for (_, field) in fields.iter() {
188                     if first {
189                         first = false;
190                     } else {
191                         write!(f, ", ")?;
192                     }
193                     // Enum variant fields must be pub.
194                     field.type_ref.hir_fmt(f)?;
195                 }
196                 write!(f, ")")?;
197             }
198             VariantData::Record(fields) => {
199                 write!(f, " {{")?;
200                 let mut first = true;
201                 for (_, field) in fields.iter() {
202                     if first {
203                         first = false;
204                         write!(f, " ")?;
205                     } else {
206                         write!(f, ", ")?;
207                     }
208                     // Enum variant fields must be pub.
209                     write!(f, "{}: ", field.name)?;
210                     field.type_ref.hir_fmt(f)?;
211                 }
212                 write!(f, " }}")?;
213             }
214         }
215         Ok(())
216     }
217 }
218
219 impl HirDisplay for Type {
220     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
221         self.ty.hir_fmt(f)
222     }
223 }
224
225 impl HirDisplay for GenericParam {
226     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
227         match self {
228             GenericParam::TypeParam(it) => it.hir_fmt(f),
229             GenericParam::LifetimeParam(it) => it.hir_fmt(f),
230             GenericParam::ConstParam(it) => it.hir_fmt(f),
231         }
232     }
233 }
234
235 impl HirDisplay for TypeParam {
236     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
237         write!(f, "{}", self.name(f.db))?;
238         if f.omit_verbose_types() {
239             return Ok(());
240         }
241
242         let bounds = f.db.generic_predicates_for_param(self.id, None);
243         let substs = TyBuilder::type_params_subst(f.db, self.id.parent);
244         let predicates: Vec<_> =
245             bounds.iter().cloned().map(|b| b.substitute(Interner, &substs)).collect();
246         let krate = self.id.parent.krate(f.db).id;
247         let sized_trait =
248             f.db.lang_item(krate, SmolStr::new_inline("sized"))
249                 .and_then(|lang_item| lang_item.as_trait());
250         let has_only_sized_bound = predicates.iter().all(move |pred| match pred.skip_binders() {
251             WhereClause::Implemented(it) => Some(it.hir_trait_id()) == sized_trait,
252             _ => false,
253         });
254         let has_only_not_sized_bound = predicates.is_empty();
255         if !has_only_sized_bound || has_only_not_sized_bound {
256             let default_sized = SizedByDefault::Sized { anchor: krate };
257             write_bounds_like_dyn_trait_with_prefix(":", &predicates, default_sized, f)?;
258         }
259         Ok(())
260     }
261 }
262
263 impl HirDisplay for LifetimeParam {
264     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
265         write!(f, "{}", self.name(f.db))
266     }
267 }
268
269 impl HirDisplay for ConstParam {
270     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
271         write!(f, "const {}: ", self.name(f.db))?;
272         self.ty(f.db).hir_fmt(f)
273     }
274 }
275
276 fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
277     let params = f.db.generic_params(def);
278     if params.lifetimes.is_empty()
279         && params.consts.is_empty()
280         && params
281             .types
282             .iter()
283             .all(|(_, param)| !matches!(param.provenance, TypeParamProvenance::TypeParamList))
284     {
285         return Ok(());
286     }
287     write!(f, "<")?;
288
289     let mut first = true;
290     let mut delim = |f: &mut HirFormatter| {
291         if first {
292             first = false;
293             Ok(())
294         } else {
295             write!(f, ", ")
296         }
297     };
298     for (_, lifetime) in params.lifetimes.iter() {
299         delim(f)?;
300         write!(f, "{}", lifetime.name)?;
301     }
302     for (_, ty) in params.types.iter() {
303         if ty.provenance != TypeParamProvenance::TypeParamList {
304             continue;
305         }
306         if let Some(name) = &ty.name {
307             delim(f)?;
308             write!(f, "{}", name)?;
309             if let Some(default) = &ty.default {
310                 write!(f, " = ")?;
311                 default.hir_fmt(f)?;
312             }
313         }
314     }
315     for (_, konst) in params.consts.iter() {
316         delim(f)?;
317         write!(f, "const {}: ", konst.name)?;
318         konst.ty.hir_fmt(f)?;
319     }
320
321     write!(f, ">")?;
322     Ok(())
323 }
324
325 fn write_where_clause(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
326     let params = f.db.generic_params(def);
327
328     // unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`.
329     let is_unnamed_type_target = |target: &WherePredicateTypeTarget| match target {
330         WherePredicateTypeTarget::TypeRef(_) => false,
331         WherePredicateTypeTarget::TypeParam(id) => params.types[*id].name.is_none(),
332     };
333
334     let has_displayable_predicate = params
335         .where_predicates
336         .iter()
337         .any(|pred| {
338             !matches!(pred, WherePredicate::TypeBound { target, .. } if is_unnamed_type_target(target))
339         });
340
341     if !has_displayable_predicate {
342         return Ok(());
343     }
344
345     let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter| match target {
346         WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f),
347         WherePredicateTypeTarget::TypeParam(id) => match &params.types[*id].name {
348             Some(name) => write!(f, "{}", name),
349             None => write!(f, "{{unnamed}}"),
350         },
351     };
352
353     write!(f, "\nwhere")?;
354
355     for (pred_idx, pred) in params.where_predicates.iter().enumerate() {
356         let prev_pred =
357             if pred_idx == 0 { None } else { Some(&params.where_predicates[pred_idx - 1]) };
358
359         let new_predicate = |f: &mut HirFormatter| {
360             write!(f, "{}", if pred_idx == 0 { "\n    " } else { ",\n    " })
361         };
362
363         match pred {
364             WherePredicate::TypeBound { target, .. } if is_unnamed_type_target(target) => {}
365             WherePredicate::TypeBound { target, bound } => {
366                 if matches!(prev_pred, Some(WherePredicate::TypeBound { target: target_, .. }) if target_ == target)
367                 {
368                     write!(f, " + ")?;
369                 } else {
370                     new_predicate(f)?;
371                     write_target(target, f)?;
372                     write!(f, ": ")?;
373                 }
374                 bound.hir_fmt(f)?;
375             }
376             WherePredicate::Lifetime { target, bound } => {
377                 if matches!(prev_pred, Some(WherePredicate::Lifetime { target: target_, .. }) if target_ == target)
378                 {
379                     write!(f, " + {}", bound.name)?;
380                 } else {
381                     new_predicate(f)?;
382                     write!(f, "{}: {}", target.name, bound.name)?;
383                 }
384             }
385             WherePredicate::ForLifetime { lifetimes, target, bound } => {
386                 if matches!(
387                     prev_pred,
388                     Some(WherePredicate::ForLifetime { lifetimes: lifetimes_, target: target_, .. })
389                     if lifetimes_ == lifetimes && target_ == target,
390                 ) {
391                     write!(f, " + ")?;
392                 } else {
393                     new_predicate(f)?;
394                     write!(f, "for<")?;
395                     for (idx, lifetime) in lifetimes.iter().enumerate() {
396                         if idx != 0 {
397                             write!(f, ", ")?;
398                         }
399                         write!(f, "{}", lifetime)?;
400                     }
401                     write!(f, "> ")?;
402                     write_target(target, f)?;
403                     write!(f, ": ")?;
404                 }
405                 bound.hir_fmt(f)?;
406             }
407         }
408     }
409
410     // End of final predicate. There must be at least one predicate here.
411     write!(f, ",")?;
412
413     Ok(())
414 }
415
416 impl HirDisplay for Const {
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.const_data(self.id);
420         write!(f, "const ")?;
421         match &data.name {
422             Some(name) => write!(f, "{}: ", name)?,
423             None => write!(f, "_: ")?,
424         }
425         data.type_ref.hir_fmt(f)?;
426         Ok(())
427     }
428 }
429
430 impl HirDisplay for Static {
431     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
432         write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
433         let data = f.db.static_data(self.id);
434         write!(f, "static ")?;
435         if data.mutable {
436             write!(f, "mut ")?;
437         }
438         write!(f, "{}: ", &data.name)?;
439         data.type_ref.hir_fmt(f)?;
440         Ok(())
441     }
442 }
443
444 impl HirDisplay for Trait {
445     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
446         write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
447         let data = f.db.trait_data(self.id);
448         if data.is_unsafe {
449             write!(f, "unsafe ")?;
450         }
451         if data.is_auto {
452             write!(f, "auto ")?;
453         }
454         write!(f, "trait {}", data.name)?;
455         let def_id = GenericDefId::TraitId(self.id);
456         write_generic_params(def_id, f)?;
457         write_where_clause(def_id, f)?;
458         Ok(())
459     }
460 }
461
462 impl HirDisplay for TypeAlias {
463     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
464         write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
465         let data = f.db.type_alias_data(self.id);
466         write!(f, "type {}", data.name)?;
467         if !data.bounds.is_empty() {
468             write!(f, ": ")?;
469             f.write_joined(&data.bounds, " + ")?;
470         }
471         if let Some(ty) = &data.type_ref {
472             write!(f, " = ")?;
473             ty.hir_fmt(f)?;
474         }
475         Ok(())
476     }
477 }
478
479 impl HirDisplay for Module {
480     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
481         // FIXME: Module doesn't have visibility saved in data.
482         match self.name(f.db) {
483             Some(name) => write!(f, "mod {}", name),
484             None if self.crate_root(f.db) == *self => match self.krate().display_name(f.db) {
485                 Some(name) => write!(f, "extern crate {}", name),
486                 None => write!(f, "extern crate {{unknown}}"),
487             },
488             None => write!(f, "mod {{unnamed}}"),
489         }
490     }
491 }