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