1#![allow(dead_code)]
3
4use std::{
5 fmt::{self, Write},
6 mem,
7};
8
9use hir_expand::{Lookup, mod_path::PathKind};
10use itertools::Itertools;
11use span::Edition;
12use syntax::ast::HasName;
13
14use crate::{
15 AdtId, DefWithBodyId, GenericDefId, TypeParamId, VariantId,
16 expr_store::path::{GenericArg, GenericArgs},
17 hir::{
18 Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, Movability, Statement,
19 generics::{GenericParams, WherePredicate},
20 },
21 lang_item::LangItemTarget,
22 signatures::{FnFlags, FunctionSignature, StructSignature},
23 src::HasSource,
24 type_ref::{ConstRef, LifetimeRef, Mutability, TraitBoundModifier, TypeBound, UseArgRef},
25};
26use crate::{LifetimeParamId, signatures::StructFlags};
27use crate::{item_tree::FieldsShape, signatures::FieldData};
28
29use super::*;
30
31macro_rules! w {
32 ($dst:expr, $($arg:tt)*) => {
33 { let _ = write!($dst, $($arg)*); }
34 };
35}
36
37macro_rules! wln {
38 ($dst:expr) => {
39 { $dst.newline(); }
40 };
41 ($dst:expr, $($arg:tt)*) => {
42 { let _ = w!($dst, $($arg)*); $dst.newline(); }
43 };
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47pub enum LineFormat {
48 Oneline,
49 Newline,
50 Indentation,
51}
52
53fn item_name<Id, Loc>(db: &dyn DefDatabase, id: Id, default: &str) -> String
54where
55 Id: Lookup<Database = dyn DefDatabase, Data = Loc>,
56 Loc: HasSource,
57 Loc::Value: ast::HasName,
58{
59 let loc = id.lookup(db);
60 let source = loc.source(db);
61 source.value.name().map_or_else(|| default.to_owned(), |name| name.to_string())
62}
63
64pub fn print_body_hir(
65 db: &dyn DefDatabase,
66 body: &Body,
67 owner: DefWithBodyId,
68 edition: Edition,
69) -> String {
70 let header = match owner {
71 DefWithBodyId::FunctionId(it) => format!("fn {}", item_name(db, it, "<missing>")),
72 DefWithBodyId::StaticId(it) => format!("static {} = ", item_name(db, it, "<missing>")),
73 DefWithBodyId::ConstId(it) => format!("const {} = ", item_name(db, it, "_")),
74 DefWithBodyId::VariantId(it) => format!(
75 "enum {}::{}",
76 item_name(db, it.lookup(db).parent, "<missing>"),
77 item_name(db, it, "<missing>")
78 ),
79 };
80
81 let mut p = Printer {
82 db,
83 store: body,
84 buf: header,
85 indent_level: 0,
86 line_format: LineFormat::Newline,
87 edition,
88 };
89 if let DefWithBodyId::FunctionId(_) = owner {
90 p.buf.push('(');
91 if let Some(self_param) = body.self_param {
92 p.print_binding(self_param);
93 p.buf.push_str(", ");
94 }
95 body.params.iter().for_each(|param| {
96 p.print_pat(*param);
97 p.buf.push_str(", ");
98 });
99 if !body.params.is_empty() {
101 p.buf.truncate(p.buf.len() - 2);
102 }
103 p.buf.push(')');
104 p.buf.push(' ');
105 }
106 p.print_expr(body.body_expr);
107 if matches!(owner, DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_)) {
108 p.buf.push(';');
109 }
110 p.buf
111}
112
113pub fn print_variant_body_hir(db: &dyn DefDatabase, owner: VariantId, edition: Edition) -> String {
114 let header = match owner {
115 VariantId::StructId(it) => format!("struct {}", item_name(db, it, "<missing>")),
116 VariantId::EnumVariantId(it) => format!(
117 "enum {}::{}",
118 item_name(db, it.lookup(db).parent, "<missing>"),
119 item_name(db, it, "<missing>")
120 ),
121 VariantId::UnionId(it) => format!("union {}", item_name(db, it, "<missing>")),
122 };
123
124 let fields = owner.fields(db);
125
126 let mut p = Printer {
127 db,
128 store: &fields.store,
129 buf: header,
130 indent_level: 0,
131 line_format: LineFormat::Newline,
132 edition,
133 };
134 match fields.shape {
135 FieldsShape::Record => wln!(p, " {{"),
136 FieldsShape::Tuple => wln!(p, "("),
137 FieldsShape::Unit => (),
138 }
139
140 for (_, data) in fields.fields().iter() {
141 let FieldData { name, type_ref, visibility, is_unsafe } = data;
142 match visibility {
143 crate::item_tree::RawVisibility::Module(interned, _visibility_explicitness) => {
144 w!(p, "pub(in {})", interned.display(db, p.edition))
145 }
146 crate::item_tree::RawVisibility::Public => w!(p, "pub "),
147 crate::item_tree::RawVisibility::PubCrate => w!(p, "pub(crate) "),
148 crate::item_tree::RawVisibility::PubSelf(_) => w!(p, "pub(self) "),
149 }
150 if *is_unsafe {
151 w!(p, "unsafe ");
152 }
153 w!(p, "{}: ", name.display(db, p.edition));
154 p.print_type_ref(*type_ref);
155 }
156
157 match fields.shape {
158 FieldsShape::Record => wln!(p, "}}"),
159 FieldsShape::Tuple => wln!(p, ");"),
160 FieldsShape::Unit => wln!(p, ";"),
161 }
162 p.buf
163}
164
165pub fn print_signature(db: &dyn DefDatabase, owner: GenericDefId, edition: Edition) -> String {
166 match owner {
167 GenericDefId::AdtId(id) => match id {
168 AdtId::StructId(id) => {
169 let signature = db.struct_signature(id);
170 print_struct(db, &signature, edition)
171 }
172 AdtId::UnionId(id) => {
173 format!("unimplemented {id:?}")
174 }
175 AdtId::EnumId(id) => {
176 format!("unimplemented {id:?}")
177 }
178 },
179 GenericDefId::ConstId(id) => format!("unimplemented {id:?}"),
180 GenericDefId::FunctionId(id) => {
181 let signature = db.function_signature(id);
182 print_function(db, &signature, edition)
183 }
184 GenericDefId::ImplId(id) => format!("unimplemented {id:?}"),
185 GenericDefId::StaticId(id) => format!("unimplemented {id:?}"),
186 GenericDefId::TraitId(id) => format!("unimplemented {id:?}"),
187 GenericDefId::TypeAliasId(id) => format!("unimplemented {id:?}"),
188 }
189}
190
191pub fn print_path(
192 db: &dyn DefDatabase,
193 store: &ExpressionStore,
194 path: &Path,
195 edition: Edition,
196) -> String {
197 let mut p = Printer {
198 db,
199 store,
200 buf: String::new(),
201 indent_level: 0,
202 line_format: LineFormat::Newline,
203 edition,
204 };
205 p.print_path(path);
206 p.buf
207}
208
209pub fn print_struct(
210 db: &dyn DefDatabase,
211 StructSignature { name, generic_params, store, flags, shape, repr }: &StructSignature,
212 edition: Edition,
213) -> String {
214 let mut p = Printer {
215 db,
216 store,
217 buf: String::new(),
218 indent_level: 0,
219 line_format: LineFormat::Newline,
220 edition,
221 };
222 if let Some(repr) = repr {
223 if repr.c() {
224 wln!(p, "#[repr(C)]");
225 }
226 if let Some(align) = repr.align {
227 wln!(p, "#[repr(align({}))]", align.bytes());
228 }
229 if let Some(pack) = repr.pack {
230 wln!(p, "#[repr(pack({}))]", pack.bytes());
231 }
232 }
233 if flags.contains(StructFlags::FUNDAMENTAL) {
234 wln!(p, "#[fundamental]");
235 }
236 w!(p, "struct ");
237 w!(p, "{}", name.display(db, edition));
238 print_generic_params(db, generic_params, &mut p);
239 match shape {
240 FieldsShape::Record => wln!(p, " {{...}}"),
241 FieldsShape::Tuple => wln!(p, "(...)"),
242 FieldsShape::Unit => (),
243 }
244
245 print_where_clauses(db, generic_params, &mut p);
246
247 match shape {
248 FieldsShape::Record => wln!(p),
249 FieldsShape::Tuple => wln!(p, ";"),
250 FieldsShape::Unit => wln!(p, ";"),
251 }
252
253 p.buf
254}
255
256pub fn print_function(
257 db: &dyn DefDatabase,
258 FunctionSignature {
259 name,
260 generic_params,
261 store,
262 params,
263 ret_type,
264 abi,
265 flags,
266 legacy_const_generics_indices,
267 }: &FunctionSignature,
268 edition: Edition,
269) -> String {
270 let mut p = Printer {
271 db,
272 store,
273 buf: String::new(),
274 indent_level: 0,
275 line_format: LineFormat::Newline,
276 edition,
277 };
278 if flags.contains(FnFlags::CONST) {
279 w!(p, "const ");
280 }
281 if flags.contains(FnFlags::ASYNC) {
282 w!(p, "async ");
283 }
284 if flags.contains(FnFlags::UNSAFE) {
285 w!(p, "unsafe ");
286 }
287 if flags.contains(FnFlags::EXPLICIT_SAFE) {
288 w!(p, "safe ");
289 }
290 if let Some(abi) = abi {
291 w!(p, "extern \"{}\" ", abi.as_str());
292 }
293 w!(p, "fn ");
294 w!(p, "{}", name.display(db, edition));
295 print_generic_params(db, generic_params, &mut p);
296 w!(p, "(");
297 for (i, param) in params.iter().enumerate() {
298 if i != 0 {
299 w!(p, ", ");
300 }
301 if legacy_const_generics_indices.as_ref().is_some_and(|idx| idx.contains(&(i as u32))) {
302 w!(p, "const: ");
303 }
304 p.print_type_ref(*param);
305 }
306 w!(p, ")");
307 if let Some(ret_type) = ret_type {
308 w!(p, " -> ");
309 p.print_type_ref(*ret_type);
310 }
311
312 print_where_clauses(db, generic_params, &mut p);
313 wln!(p, " {{...}}");
314
315 p.buf
316}
317
318fn print_where_clauses(db: &dyn DefDatabase, generic_params: &GenericParams, p: &mut Printer<'_>) {
319 if !generic_params.where_predicates.is_empty() {
320 w!(p, "\nwhere\n");
321 p.indented(|p| {
322 for (i, pred) in generic_params.where_predicates.iter().enumerate() {
323 if i != 0 {
324 w!(p, ",\n");
325 }
326 match pred {
327 WherePredicate::TypeBound { target, bound } => {
328 p.print_type_ref(*target);
329 w!(p, ": ");
330 p.print_type_bounds(std::slice::from_ref(bound));
331 }
332 WherePredicate::Lifetime { target, bound } => {
333 p.print_lifetime_ref(*target);
334 w!(p, ": ");
335 p.print_lifetime_ref(*bound);
336 }
337 WherePredicate::ForLifetime { lifetimes, target, bound } => {
338 w!(p, "for<");
339 for (i, lifetime) in lifetimes.iter().enumerate() {
340 if i != 0 {
341 w!(p, ", ");
342 }
343 w!(p, "{}", lifetime.display(db, p.edition));
344 }
345 w!(p, "> ");
346 p.print_type_ref(*target);
347 w!(p, ": ");
348 p.print_type_bounds(std::slice::from_ref(bound));
349 }
350 }
351 }
352 });
353 wln!(p);
354 }
355}
356
357fn print_generic_params(db: &dyn DefDatabase, generic_params: &GenericParams, p: &mut Printer<'_>) {
358 if !generic_params.is_empty() {
359 w!(p, "<");
360 let mut first = true;
361 for (_i, param) in generic_params.iter_lt() {
362 if !first {
363 w!(p, ", ");
364 }
365 first = false;
366 w!(p, "{}", param.name.display(db, p.edition));
367 }
368 for (i, param) in generic_params.iter_type_or_consts() {
369 if !first {
370 w!(p, ", ");
371 }
372 first = false;
373 if let Some(const_param) = param.const_param() {
374 w!(p, "const {}: ", const_param.name.display(db, p.edition));
375 p.print_type_ref(const_param.ty);
376 if let Some(default) = const_param.default {
377 w!(p, " = ");
378 p.print_expr(default.expr);
379 }
380 }
381 if let Some(type_param) = param.type_param() {
382 match &type_param.name {
383 Some(name) => w!(p, "{}", name.display(db, p.edition)),
384 None => w!(p, "Param[{}]", i.into_raw()),
385 }
386 if let Some(default) = type_param.default {
387 w!(p, " = ");
388 p.print_type_ref(default);
389 }
390 }
391 }
392 w!(p, ">");
393 }
394}
395
396pub fn print_expr_hir(
397 db: &dyn DefDatabase,
398 store: &ExpressionStore,
399 _owner: DefWithBodyId,
400 expr: ExprId,
401 edition: Edition,
402) -> String {
403 let mut p = Printer {
404 db,
405 store,
406 buf: String::new(),
407 indent_level: 0,
408 line_format: LineFormat::Newline,
409 edition,
410 };
411 p.print_expr(expr);
412 p.buf
413}
414
415pub fn print_pat_hir(
416 db: &dyn DefDatabase,
417 store: &ExpressionStore,
418 _owner: DefWithBodyId,
419 pat: PatId,
420 oneline: bool,
421 edition: Edition,
422) -> String {
423 let mut p = Printer {
424 db,
425 store,
426 buf: String::new(),
427 indent_level: 0,
428 line_format: if oneline { LineFormat::Oneline } else { LineFormat::Newline },
429 edition,
430 };
431 p.print_pat(pat);
432 p.buf
433}
434
435struct Printer<'a> {
436 db: &'a dyn DefDatabase,
437 store: &'a ExpressionStore,
438 buf: String,
439 indent_level: usize,
440 line_format: LineFormat,
441 edition: Edition,
442}
443
444impl Write for Printer<'_> {
445 fn write_str(&mut self, s: &str) -> fmt::Result {
446 for line in s.split_inclusive('\n') {
447 if matches!(self.line_format, LineFormat::Indentation) {
448 match self.buf.chars().rev().find(|ch| *ch != ' ') {
449 Some('\n') | None => {}
450 _ => self.buf.push('\n'),
451 }
452 self.buf.push_str(&" ".repeat(self.indent_level));
453 }
454
455 self.buf.push_str(line);
456
457 if matches!(self.line_format, LineFormat::Newline | LineFormat::Indentation) {
458 self.line_format = if line.ends_with('\n') {
459 LineFormat::Indentation
460 } else {
461 LineFormat::Newline
462 };
463 }
464 }
465
466 Ok(())
467 }
468}
469
470impl Printer<'_> {
471 fn indented(&mut self, f: impl FnOnce(&mut Self)) {
472 self.indent_level += 1;
473 wln!(self);
474 f(self);
475 self.indent_level -= 1;
476 self.buf = self.buf.trim_end_matches('\n').to_owned();
477 }
478
479 fn whitespace(&mut self) {
480 match self.buf.chars().next_back() {
481 None | Some('\n' | ' ') => {}
482 _ => self.buf.push(' '),
483 }
484 }
485
486 fn newline(&mut self) {
492 if matches!(self.line_format, LineFormat::Oneline) {
493 match self.buf.chars().last() {
494 Some(' ') | None => {}
495 Some(_) => {
496 w!(self, " ");
497 }
498 }
499 } else {
500 match self.buf.chars().rev().find_position(|ch| *ch != ' ') {
501 Some((_, '\n')) | None => {}
502 Some((idx, _)) => {
503 if idx != 0 {
504 self.buf.drain(self.buf.len() - idx..);
505 }
506 w!(self, "\n");
507 }
508 }
509 }
510 }
511
512 fn print_expr(&mut self, expr: ExprId) {
513 let expr = &self.store[expr];
514
515 match expr {
516 Expr::Missing => w!(self, "�"),
517 Expr::Underscore => w!(self, "_"),
518 Expr::InlineAsm(_) => w!(self, "builtin#asm(_)"),
519 Expr::OffsetOf(offset_of) => {
520 w!(self, "builtin#offset_of(");
521 self.print_type_ref(offset_of.container);
522 let edition = self.edition;
523 w!(
524 self,
525 ", {})",
526 offset_of
527 .fields
528 .iter()
529 .format_with(".", |field, f| f(&field.display(self.db, edition)))
530 );
531 }
532 Expr::Path(path) => self.print_path(path),
533 Expr::If { condition, then_branch, else_branch } => {
534 w!(self, "if ");
535 self.print_expr(*condition);
536 w!(self, " ");
537 self.print_expr(*then_branch);
538 if let Some(els) = *else_branch {
539 w!(self, " else ");
540 self.print_expr(els);
541 }
542 }
543 Expr::Let { pat, expr } => {
544 w!(self, "let ");
545 self.print_pat(*pat);
546 w!(self, " = ");
547 self.print_expr(*expr);
548 }
549 Expr::Loop { body, label } => {
550 if let Some(lbl) = label {
551 w!(self, "{}: ", self.store[*lbl].name.display(self.db, self.edition));
552 }
553 w!(self, "loop ");
554 self.print_expr(*body);
555 }
556 Expr::Call { callee, args } => {
557 self.print_expr(*callee);
558 w!(self, "(");
559 if !args.is_empty() {
560 self.indented(|p| {
561 for arg in &**args {
562 p.print_expr(*arg);
563 wln!(p, ",");
564 }
565 });
566 }
567 w!(self, ")");
568 }
569 Expr::MethodCall { receiver, method_name, args, generic_args } => {
570 self.print_expr(*receiver);
571 w!(self, ".{}", method_name.display(self.db, self.edition));
572 if let Some(args) = generic_args {
573 w!(self, "::<");
574 self.print_generic_args(args);
575 w!(self, ">");
576 }
577 w!(self, "(");
578 if !args.is_empty() {
579 self.indented(|p| {
580 for arg in &**args {
581 p.print_expr(*arg);
582 wln!(p, ",");
583 }
584 });
585 }
586 w!(self, ")");
587 }
588 Expr::Match { expr, arms } => {
589 w!(self, "match ");
590 self.print_expr(*expr);
591 w!(self, " {{");
592 self.indented(|p| {
593 for arm in &**arms {
594 p.print_pat(arm.pat);
595 if let Some(guard) = arm.guard {
596 w!(p, " if ");
597 p.print_expr(guard);
598 }
599 w!(p, " => ");
600 p.print_expr(arm.expr);
601 wln!(p, ",");
602 }
603 });
604 wln!(self, "}}");
605 }
606 Expr::Continue { label } => {
607 w!(self, "continue");
608 if let Some(lbl) = label {
609 w!(self, " {}", self.store[*lbl].name.display(self.db, self.edition));
610 }
611 }
612 Expr::Break { expr, label } => {
613 w!(self, "break");
614 if let Some(lbl) = label {
615 w!(self, " {}", self.store[*lbl].name.display(self.db, self.edition));
616 }
617 if let Some(expr) = expr {
618 self.whitespace();
619 self.print_expr(*expr);
620 }
621 }
622 Expr::Return { expr } => {
623 w!(self, "return");
624 if let Some(expr) = expr {
625 self.whitespace();
626 self.print_expr(*expr);
627 }
628 }
629 Expr::Become { expr } => {
630 w!(self, "become");
631 self.whitespace();
632 self.print_expr(*expr);
633 }
634 Expr::Yield { expr } => {
635 w!(self, "yield");
636 if let Some(expr) = expr {
637 self.whitespace();
638 self.print_expr(*expr);
639 }
640 }
641 Expr::Yeet { expr } => {
642 w!(self, "do");
643 self.whitespace();
644 w!(self, "yeet");
645 if let Some(expr) = expr {
646 self.whitespace();
647 self.print_expr(*expr);
648 }
649 }
650 Expr::RecordLit { path, fields, spread } => {
651 match path {
652 Some(path) => self.print_path(path),
653 None => w!(self, "�"),
654 }
655
656 w!(self, "{{");
657 let edition = self.edition;
658 self.indented(|p| {
659 for field in &**fields {
660 w!(p, "{}: ", field.name.display(self.db, edition));
661 p.print_expr(field.expr);
662 wln!(p, ",");
663 }
664 if let Some(spread) = spread {
665 w!(p, "..");
666 p.print_expr(*spread);
667 wln!(p);
668 }
669 });
670 w!(self, "}}");
671 }
672 Expr::Field { expr, name } => {
673 self.print_expr(*expr);
674 w!(self, ".{}", name.display(self.db, self.edition));
675 }
676 Expr::Await { expr } => {
677 self.print_expr(*expr);
678 w!(self, ".await");
679 }
680 Expr::Cast { expr, type_ref } => {
681 self.print_expr(*expr);
682 w!(self, " as ");
683 self.print_type_ref(*type_ref);
684 }
685 Expr::Ref { expr, rawness, mutability } => {
686 w!(self, "&");
687 if rawness.is_raw() {
688 w!(self, "raw ");
689 }
690 if mutability.is_mut() {
691 w!(self, "mut ");
692 }
693 self.print_expr(*expr);
694 }
695 Expr::Box { expr } => {
696 w!(self, "box ");
697 self.print_expr(*expr);
698 }
699 Expr::UnaryOp { expr, op } => {
700 let op = match op {
701 ast::UnaryOp::Deref => "*",
702 ast::UnaryOp::Not => "!",
703 ast::UnaryOp::Neg => "-",
704 };
705 w!(self, "{}", op);
706 self.print_expr(*expr);
707 }
708 Expr::BinaryOp { lhs, rhs, op } => {
709 let (bra, ket) = match op {
710 None | Some(ast::BinaryOp::Assignment { .. }) => ("", ""),
711 _ => ("(", ")"),
712 };
713 w!(self, "{}", bra);
714 self.print_expr(*lhs);
715 w!(self, "{} ", ket);
716 match op {
717 Some(op) => w!(self, "{}", op),
718 None => w!(self, "�"), }
720 w!(self, " {}", bra);
721 self.print_expr(*rhs);
722 w!(self, "{}", ket);
723 }
724 Expr::Range { lhs, rhs, range_type } => {
725 if let Some(lhs) = lhs {
726 w!(self, "(");
727 self.print_expr(*lhs);
728 w!(self, ") ");
729 }
730 let range = match range_type {
731 ast::RangeOp::Exclusive => "..",
732 ast::RangeOp::Inclusive => "..=",
733 };
734 w!(self, "{}", range);
735 if let Some(rhs) = rhs {
736 w!(self, "(");
737 self.print_expr(*rhs);
738 w!(self, ") ");
739 }
740 }
741 Expr::Index { base, index } => {
742 self.print_expr(*base);
743 w!(self, "[");
744 self.print_expr(*index);
745 w!(self, "]");
746 }
747 Expr::Closure { args, arg_types, ret_type, body, closure_kind, capture_by } => {
748 match closure_kind {
749 ClosureKind::Coroutine(Movability::Static) => {
750 w!(self, "static ");
751 }
752 ClosureKind::Async => {
753 w!(self, "async ");
754 }
755 _ => (),
756 }
757 match capture_by {
758 CaptureBy::Value => {
759 w!(self, "move ");
760 }
761 CaptureBy::Ref => (),
762 }
763 w!(self, "|");
764 for (i, (pat, ty)) in args.iter().zip(arg_types.iter()).enumerate() {
765 if i != 0 {
766 w!(self, ", ");
767 }
768 self.print_pat(*pat);
769 if let Some(ty) = ty {
770 w!(self, ": ");
771 self.print_type_ref(*ty);
772 }
773 }
774 w!(self, "|");
775 if let Some(ret_ty) = ret_type {
776 w!(self, " -> ");
777 self.print_type_ref(*ret_ty);
778 }
779 self.whitespace();
780 self.print_expr(*body);
781 }
782 Expr::Tuple { exprs } => {
783 w!(self, "(");
784 for expr in exprs.iter() {
785 self.print_expr(*expr);
786 w!(self, ", ");
787 }
788 w!(self, ")");
789 }
790 Expr::Array(arr) => {
791 w!(self, "[");
792 if !matches!(arr, Array::ElementList { elements, .. } if elements.is_empty()) {
793 self.indented(|p| match arr {
794 Array::ElementList { elements } => {
795 for elem in elements.iter() {
796 p.print_expr(*elem);
797 w!(p, ", ");
798 }
799 }
800 Array::Repeat { initializer, repeat } => {
801 p.print_expr(*initializer);
802 w!(p, "; ");
803 p.print_expr(*repeat);
804 }
805 });
806 self.newline();
807 }
808 w!(self, "]");
809 }
810 Expr::Literal(lit) => self.print_literal(lit),
811 Expr::Block { id: _, statements, tail, label } => {
812 let label = label.map(|lbl| {
813 format!("{}: ", self.store[lbl].name.display(self.db, self.edition))
814 });
815 self.print_block(label.as_deref(), statements, tail);
816 }
817 Expr::Unsafe { id: _, statements, tail } => {
818 self.print_block(Some("unsafe "), statements, tail);
819 }
820 Expr::Async { id: _, statements, tail } => {
821 self.print_block(Some("async "), statements, tail);
822 }
823 Expr::Const(id) => {
824 w!(self, "const {{ /* {id:?} */ }}");
825 }
826 &Expr::Assignment { target, value } => {
827 self.print_pat(target);
828 w!(self, " = ");
829 self.print_expr(value);
830 }
831 }
832 }
833
834 fn print_block(
835 &mut self,
836 label: Option<&str>,
837 statements: &[Statement],
838 tail: &Option<la_arena::Idx<Expr>>,
839 ) {
840 self.whitespace();
841 if let Some(lbl) = label {
842 w!(self, "{}", lbl);
843 }
844 w!(self, "{{");
845 if !statements.is_empty() || tail.is_some() {
846 self.indented(|p| {
847 for stmt in statements {
848 p.print_stmt(stmt);
849 }
850 if let Some(tail) = tail {
851 p.print_expr(*tail);
852 }
853 p.newline();
854 });
855 }
856 w!(self, "}}");
857 }
858
859 fn print_pat(&mut self, pat: PatId) {
860 let pat = &self.store[pat];
861
862 match pat {
863 Pat::Missing => w!(self, "�"),
864 Pat::Wild => w!(self, "_"),
865 Pat::Tuple { args, ellipsis } => {
866 w!(self, "(");
867 for (i, pat) in args.iter().enumerate() {
868 if i != 0 {
869 w!(self, ", ");
870 }
871 if *ellipsis == Some(i as u32) {
872 w!(self, ".., ");
873 }
874 self.print_pat(*pat);
875 }
876 w!(self, ")");
877 }
878 Pat::Or(pats) => {
879 w!(self, "(");
880 for (i, pat) in pats.iter().enumerate() {
881 if i != 0 {
882 w!(self, " | ");
883 }
884 self.print_pat(*pat);
885 }
886 w!(self, ")");
887 }
888 Pat::Record { path, args, ellipsis } => {
889 match path {
890 Some(path) => self.print_path(path),
891 None => w!(self, "�"),
892 }
893
894 w!(self, " {{");
895 let edition = self.edition;
896 let oneline = matches!(self.line_format, LineFormat::Oneline);
897 self.indented(|p| {
898 for (idx, arg) in args.iter().enumerate() {
899 let field_name = arg.name.display(self.db, edition).to_string();
900
901 let mut same_name = false;
902 if let Pat::Bind { id, subpat: None } = &self.store[arg.pat]
903 && let Binding { name, mode: BindingAnnotation::Unannotated, .. } =
904 &self.store.assert_expr_only().bindings[*id]
905 && name.as_str() == field_name
906 {
907 same_name = true;
908 }
909
910 w!(p, "{}", field_name);
911
912 if !same_name {
913 w!(p, ": ");
914 p.print_pat(arg.pat);
915 }
916
917 if oneline && idx == args.len() - 1 {
919 w!(p, " ");
920 } else {
921 wln!(p, ",");
922 }
923 }
924
925 if *ellipsis {
926 wln!(p, "..");
927 }
928 });
929 w!(self, "}}");
930 }
931 Pat::Range { start, end } => {
932 if let Some(start) = start {
933 self.print_expr(*start);
934 }
935 w!(self, "..=");
936 if let Some(end) = end {
937 self.print_expr(*end);
938 }
939 }
940 Pat::Slice { prefix, slice, suffix } => {
941 w!(self, "[");
942 for pat in prefix.iter() {
943 self.print_pat(*pat);
944 w!(self, ", ");
945 }
946 if let Some(pat) = slice {
947 self.print_pat(*pat);
948 w!(self, ", ");
949 }
950 for pat in suffix.iter() {
951 self.print_pat(*pat);
952 w!(self, ", ");
953 }
954 w!(self, "]");
955 }
956 Pat::Path(path) => self.print_path(path),
957 Pat::Lit(expr) => self.print_expr(*expr),
958 Pat::Bind { id, subpat } => {
959 self.print_binding(*id);
960 if let Some(pat) = subpat {
961 self.whitespace();
962 w!(self, "@ ");
963 self.print_pat(*pat);
964 }
965 }
966 Pat::TupleStruct { path, args, ellipsis } => {
967 match path {
968 Some(path) => self.print_path(path),
969 None => w!(self, "�"),
970 }
971 w!(self, "(");
972 for (i, arg) in args.iter().enumerate() {
973 if i != 0 {
974 w!(self, ", ");
975 }
976 if *ellipsis == Some(i as u32) {
977 w!(self, ", ..");
978 }
979 self.print_pat(*arg);
980 }
981 w!(self, ")");
982 }
983 Pat::Ref { pat, mutability } => {
984 w!(self, "&");
985 if mutability.is_mut() {
986 w!(self, "mut ");
987 }
988 self.print_pat(*pat);
989 }
990 Pat::Box { inner } => {
991 w!(self, "box ");
992 self.print_pat(*inner);
993 }
994 Pat::ConstBlock(c) => {
995 w!(self, "const ");
996 self.print_expr(*c);
997 }
998 Pat::Expr(expr) => {
999 self.print_expr(*expr);
1000 }
1001 }
1002 }
1003
1004 fn print_stmt(&mut self, stmt: &Statement) {
1005 match stmt {
1006 Statement::Let { pat, type_ref, initializer, else_branch } => {
1007 w!(self, "let ");
1008 self.print_pat(*pat);
1009 if let Some(ty) = type_ref {
1010 w!(self, ": ");
1011 self.print_type_ref(*ty);
1012 }
1013 if let Some(init) = initializer {
1014 w!(self, " = ");
1015 self.print_expr(*init);
1016 }
1017 if let Some(els) = else_branch {
1018 w!(self, " else ");
1019 self.print_expr(*els);
1020 }
1021 wln!(self, ";");
1022 }
1023 Statement::Expr { expr, has_semi } => {
1024 self.print_expr(*expr);
1025 if *has_semi {
1026 w!(self, ";");
1027 }
1028 wln!(self);
1029 }
1030 Statement::Item(_) => (),
1031 }
1032 }
1033
1034 fn print_literal(&mut self, literal: &Literal) {
1035 match literal {
1036 Literal::String(it) => w!(self, "{:?}", it),
1037 Literal::ByteString(it) => w!(self, "\"{}\"", it.escape_ascii()),
1038 Literal::CString(it) => w!(self, "\"{}\\0\"", it.escape_ascii()),
1039 Literal::Char(it) => w!(self, "'{}'", it.escape_debug()),
1040 Literal::Bool(it) => w!(self, "{}", it),
1041 Literal::Int(i, suffix) => {
1042 w!(self, "{}", i);
1043 if let Some(suffix) = suffix {
1044 w!(self, "{}", suffix);
1045 }
1046 }
1047 Literal::Uint(i, suffix) => {
1048 w!(self, "{}", i);
1049 if let Some(suffix) = suffix {
1050 w!(self, "{}", suffix);
1051 }
1052 }
1053 Literal::Float(f, suffix) => {
1054 w!(self, "{}", f);
1055 if let Some(suffix) = suffix {
1056 w!(self, "{}", suffix);
1057 }
1058 }
1059 }
1060 }
1061
1062 fn print_binding(&mut self, id: BindingId) {
1063 let Binding { name, mode, .. } = &self.store.assert_expr_only().bindings[id];
1064 let mode = match mode {
1065 BindingAnnotation::Unannotated => "",
1066 BindingAnnotation::Mutable => "mut ",
1067 BindingAnnotation::Ref => "ref ",
1068 BindingAnnotation::RefMut => "ref mut ",
1069 };
1070 w!(self, "{}{}", mode, name.display(self.db, self.edition));
1071 }
1072
1073 fn print_path(&mut self, path: &Path) {
1074 if let Path::LangItem(it, s) = path {
1075 w!(self, "builtin#lang(");
1076 macro_rules! write_name {
1077 ($it:ident) => {{
1078 w!(self, "{}", item_name(self.db, $it, "<missing>"));
1079 }};
1080 }
1081 match *it {
1082 LangItemTarget::ImplDef(it) => w!(self, "{it:?}"),
1083 LangItemTarget::EnumId(it) => write_name!(it),
1084 LangItemTarget::Function(it) => write_name!(it),
1085 LangItemTarget::Static(it) => write_name!(it),
1086 LangItemTarget::Struct(it) => write_name!(it),
1087 LangItemTarget::Union(it) => write_name!(it),
1088 LangItemTarget::TypeAlias(it) => write_name!(it),
1089 LangItemTarget::Trait(it) => write_name!(it),
1090 LangItemTarget::EnumVariant(it) => write_name!(it),
1091 }
1092
1093 if let Some(s) = s {
1094 w!(self, "::{}", s.display(self.db, self.edition));
1095 }
1096 return w!(self, ")");
1097 }
1098 match path.type_anchor() {
1099 Some(anchor) => {
1100 w!(self, "<");
1101 self.print_type_ref(anchor);
1102 w!(self, ">::");
1103 }
1104 None => match path.kind() {
1105 PathKind::Plain => {}
1106 &PathKind::SELF => w!(self, "self"),
1107 PathKind::Super(n) => {
1108 for i in 0..*n {
1109 if i == 0 {
1110 w!(self, "super");
1111 } else {
1112 w!(self, "::super");
1113 }
1114 }
1115 }
1116 PathKind::Crate => w!(self, "crate"),
1117 PathKind::Abs => {}
1118 PathKind::DollarCrate(krate) => w!(
1119 self,
1120 "{}",
1121 krate
1122 .extra_data(self.db)
1123 .display_name
1124 .as_ref()
1125 .map(|it| it.crate_name().symbol().as_str())
1126 .unwrap_or("$crate")
1127 ),
1128 },
1129 }
1130
1131 for (i, segment) in path.segments().iter().enumerate() {
1132 if i != 0 || !matches!(path.kind(), PathKind::Plain) {
1133 w!(self, "::");
1134 }
1135
1136 w!(self, "{}", segment.name.display(self.db, self.edition));
1137 if let Some(generics) = segment.args_and_bindings {
1138 w!(self, "::<");
1139 self.print_generic_args(generics);
1140
1141 w!(self, ">");
1142 }
1143 }
1144 }
1145
1146 pub(crate) fn print_generic_args(&mut self, generics: &GenericArgs) {
1147 let mut first = true;
1148 let args = if generics.has_self_type {
1149 let (self_ty, args) = generics.args.split_first().unwrap();
1150 w!(self, "Self=");
1151 self.print_generic_arg(self_ty);
1152 first = false;
1153 args
1154 } else {
1155 &generics.args
1156 };
1157 for arg in args {
1158 if !first {
1159 w!(self, ", ");
1160 }
1161 first = false;
1162 self.print_generic_arg(arg);
1163 }
1164 for binding in generics.bindings.iter() {
1165 if !first {
1166 w!(self, ", ");
1167 }
1168 first = false;
1169 w!(self, "{}", binding.name.display(self.db, self.edition));
1170 if !binding.bounds.is_empty() {
1171 w!(self, ": ");
1172 self.print_type_bounds(&binding.bounds);
1173 }
1174 if let Some(ty) = binding.type_ref {
1175 w!(self, " = ");
1176 self.print_type_ref(ty);
1177 }
1178 }
1179 }
1180
1181 pub(crate) fn print_generic_arg(&mut self, arg: &GenericArg) {
1182 match arg {
1183 GenericArg::Type(ty) => self.print_type_ref(*ty),
1184 GenericArg::Const(ConstRef { expr }) => self.print_expr(*expr),
1185 GenericArg::Lifetime(lt) => self.print_lifetime_ref(*lt),
1186 }
1187 }
1188
1189 pub(crate) fn print_type_param(&mut self, param: TypeParamId) {
1190 let generic_params = self.db.generic_params(param.parent());
1191
1192 match generic_params[param.local_id()].name() {
1193 Some(name) => w!(self, "{}", name.display(self.db, self.edition)),
1194 None => w!(self, "Param[{}]", param.local_id().into_raw()),
1195 }
1196 }
1197
1198 pub(crate) fn print_lifetime_param(&mut self, param: LifetimeParamId) {
1199 let generic_params = self.db.generic_params(param.parent);
1200 w!(self, "{}", generic_params[param.local_id].name.display(self.db, self.edition))
1201 }
1202
1203 pub(crate) fn print_lifetime_ref(&mut self, lt_ref: LifetimeRefId) {
1204 match &self.store[lt_ref] {
1205 LifetimeRef::Static => w!(self, "'static"),
1206 LifetimeRef::Named(lt) => {
1207 w!(self, "{}", lt.display(self.db, self.edition))
1208 }
1209 LifetimeRef::Placeholder => w!(self, "'_"),
1210 LifetimeRef::Error => w!(self, "'{{error}}"),
1211 &LifetimeRef::Param(p) => self.print_lifetime_param(p),
1212 }
1213 }
1214
1215 pub(crate) fn print_type_ref(&mut self, type_ref: TypeRefId) {
1216 match &self.store[type_ref] {
1218 TypeRef::Never => w!(self, "!"),
1219 &TypeRef::TypeParam(p) => self.print_type_param(p),
1220 TypeRef::Placeholder => w!(self, "_"),
1221 TypeRef::Tuple(fields) => {
1222 w!(self, "(");
1223 for (i, field) in fields.iter().enumerate() {
1224 if i != 0 {
1225 w!(self, ", ");
1226 }
1227 self.print_type_ref(*field);
1228 }
1229 w!(self, ")");
1230 }
1231 TypeRef::Path(path) => self.print_path(path),
1232 TypeRef::RawPtr(pointee, mtbl) => {
1233 let mtbl = match mtbl {
1234 Mutability::Shared => "*const",
1235 Mutability::Mut => "*mut",
1236 };
1237 w!(self, "{mtbl} ");
1238 self.print_type_ref(*pointee);
1239 }
1240 TypeRef::Reference(ref_) => {
1241 let mtbl = match ref_.mutability {
1242 Mutability::Shared => "",
1243 Mutability::Mut => "mut ",
1244 };
1245 w!(self, "&");
1246 if let Some(lt) = &ref_.lifetime {
1247 self.print_lifetime_ref(*lt);
1248 w!(self, " ");
1249 }
1250 w!(self, "{mtbl}");
1251 self.print_type_ref(ref_.ty);
1252 }
1253 TypeRef::Array(array) => {
1254 w!(self, "[");
1255 self.print_type_ref(array.ty);
1256 w!(self, "; ");
1257 self.print_generic_arg(&GenericArg::Const(array.len));
1258 w!(self, "]");
1259 }
1260 TypeRef::Slice(elem) => {
1261 w!(self, "[");
1262 self.print_type_ref(*elem);
1263 w!(self, "]");
1264 }
1265 TypeRef::Fn(fn_) => {
1266 let ((_, return_type), args) =
1267 fn_.params.split_last().expect("TypeRef::Fn is missing return type");
1268 if fn_.is_unsafe {
1269 w!(self, "unsafe ");
1270 }
1271 if let Some(abi) = &fn_.abi {
1272 w!(self, "extern ");
1273 w!(self, "{}", abi.as_str());
1274 w!(self, " ");
1275 }
1276 w!(self, "fn(");
1277 for (i, (_, typeref)) in args.iter().enumerate() {
1278 if i != 0 {
1279 w!(self, ", ");
1280 }
1281 self.print_type_ref(*typeref);
1282 }
1283 if fn_.is_varargs {
1284 if !args.is_empty() {
1285 w!(self, ", ");
1286 }
1287 w!(self, "...");
1288 }
1289 w!(self, ") -> ");
1290 self.print_type_ref(*return_type);
1291 }
1292 TypeRef::Error => w!(self, "{{error}}"),
1293 TypeRef::ImplTrait(bounds) => {
1294 w!(self, "impl ");
1295 self.print_type_bounds(bounds);
1296 }
1297 TypeRef::DynTrait(bounds) => {
1298 w!(self, "dyn ");
1299 self.print_type_bounds(bounds);
1300 }
1301 }
1302 }
1303
1304 pub(crate) fn print_type_bounds(&mut self, bounds: &[TypeBound]) {
1305 for (i, bound) in bounds.iter().enumerate() {
1306 if i != 0 {
1307 w!(self, " + ");
1308 }
1309
1310 match bound {
1311 TypeBound::Path(path, modifier) => {
1312 match modifier {
1313 TraitBoundModifier::None => (),
1314 TraitBoundModifier::Maybe => w!(self, "?"),
1315 }
1316 self.print_path(&self.store[*path]);
1317 }
1318 TypeBound::ForLifetime(lifetimes, path) => {
1319 w!(
1320 self,
1321 "for<{}> ",
1322 lifetimes
1323 .iter()
1324 .map(|it| it.display(self.db, self.edition))
1325 .format(", ")
1326 .to_string()
1327 );
1328 self.print_path(&self.store[*path]);
1329 }
1330 TypeBound::Lifetime(lt) => self.print_lifetime_ref(*lt),
1331 TypeBound::Use(args) => {
1332 w!(self, "use<");
1333 let mut first = true;
1334 for arg in args {
1335 if !mem::take(&mut first) {
1336 w!(self, ", ");
1337 }
1338 match arg {
1339 UseArgRef::Name(it) => {
1340 w!(self, "{}", it.display(self.db, self.edition))
1341 }
1342 UseArgRef::Lifetime(it) => self.print_lifetime_ref(*it),
1343 }
1344 }
1345 w!(self, ">")
1346 }
1347 TypeBound::Error => w!(self, "{{unknown}}"),
1348 }
1349 }
1350 }
1351}