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