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