1pub mod visit;
17
18use std::{borrow::Cow, fmt};
19
20use flux_common::{bug, span_bug};
21use flux_rustc_bridge::def_id_to_string;
22use flux_syntax::surface::ParamMode;
23pub use flux_syntax::surface::{BinOp, UnOp};
24use itertools::Itertools;
25use rustc_abi;
26pub use rustc_abi::VariantIdx;
27use rustc_ast::TraitObjectSyntax;
28use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
29use rustc_hash::FxHashMap;
30pub use rustc_hir::PrimTy;
31use rustc_hir::{
32 FnHeader, OwnerId, ParamName, Safety,
33 def::DefKind,
34 def_id::{DefId, LocalDefId},
35};
36use rustc_index::newtype_index;
37use rustc_macros::{Decodable, Encodable};
38pub use rustc_middle::mir::Mutability;
39use rustc_middle::{middle::resolve_bound_vars::ResolvedArg, ty::TyCtxt};
40use rustc_span::{ErrorGuaranteed, Span, Symbol, symbol::Ident};
41
42use crate::def_id::{FluxDefId, FluxLocalDefId, MaybeExternId};
43
44#[derive(Debug, Eq, PartialEq, Copy, Clone)]
46pub enum Ignored {
47 Yes,
48 No,
49}
50
51impl Ignored {
52 pub fn to_bool(self) -> bool {
53 match self {
54 Ignored::Yes => true,
55 Ignored::No => false,
56 }
57 }
58}
59
60impl From<bool> for Ignored {
61 fn from(value: bool) -> Self {
62 if value { Ignored::Yes } else { Ignored::No }
63 }
64}
65
66#[derive(Debug, Eq, PartialEq, Copy, Clone)]
68pub enum Trusted {
69 Yes,
70 No,
71}
72
73impl Trusted {
74 pub fn to_bool(self) -> bool {
75 match self {
76 Trusted::Yes => true,
77 Trusted::No => false,
78 }
79 }
80}
81
82impl From<bool> for Trusted {
83 fn from(value: bool) -> Self {
84 if value { Trusted::Yes } else { Trusted::No }
85 }
86}
87
88#[derive(Debug, Clone, Copy)]
89pub struct Generics<'fhir> {
90 pub params: &'fhir [GenericParam<'fhir>],
91 pub refinement_params: &'fhir [RefineParam<'fhir>],
92 pub predicates: Option<&'fhir [WhereBoundPredicate<'fhir>]>,
93}
94
95#[derive(Debug, Clone, Copy)]
96pub struct GenericParam<'fhir> {
97 pub def_id: MaybeExternId,
98 pub name: ParamName,
99 pub kind: GenericParamKind<'fhir>,
100}
101
102#[derive(Debug, Clone, Copy)]
103pub enum GenericParamKind<'fhir> {
104 Type { default: Option<Ty<'fhir>> },
105 Lifetime,
106 Const { ty: Ty<'fhir> },
107}
108
109#[derive(Debug)]
110pub struct Qualifier<'fhir> {
111 pub def_id: FluxLocalDefId,
112 pub args: &'fhir [RefineParam<'fhir>],
113 pub expr: Expr<'fhir>,
114 pub global: bool,
115}
116
117#[derive(Clone, Copy, Debug)]
118pub enum Node<'fhir> {
119 Item(&'fhir Item<'fhir>),
120 TraitItem(&'fhir TraitItem<'fhir>),
121 ImplItem(&'fhir ImplItem<'fhir>),
122 OpaqueTy(&'fhir OpaqueTy<'fhir>),
123 ForeignItem(&'fhir ForeignItem<'fhir>),
124 Ctor,
125 AnonConst,
126 Expr,
127}
128
129impl<'fhir> Node<'fhir> {
130 pub fn as_owner(self) -> Option<OwnerNode<'fhir>> {
131 match self {
132 Node::Item(item) => Some(OwnerNode::Item(item)),
133 Node::TraitItem(trait_item) => Some(OwnerNode::TraitItem(trait_item)),
134 Node::ImplItem(impl_item) => Some(OwnerNode::ImplItem(impl_item)),
135 Node::ForeignItem(foreign_item) => Some(OwnerNode::ForeignItem(foreign_item)),
136 Node::OpaqueTy(_) => None,
137 Node::AnonConst => None,
138 Node::Expr => None,
139 Node::Ctor => None,
140 }
141 }
142
143 pub fn expect_opaque_ty(&self) -> &'fhir OpaqueTy<'fhir> {
144 if let Node::OpaqueTy(opaque_ty) = &self { opaque_ty } else { bug!("expected opaque type") }
145 }
146}
147
148#[derive(Clone, Copy, Debug)]
149pub enum OwnerNode<'fhir> {
150 Item(&'fhir Item<'fhir>),
151 TraitItem(&'fhir TraitItem<'fhir>),
152 ImplItem(&'fhir ImplItem<'fhir>),
153 ForeignItem(&'fhir ForeignItem<'fhir>),
154}
155
156impl<'fhir> OwnerNode<'fhir> {
157 pub fn fn_sig(&self) -> Option<&'fhir FnSig<'fhir>> {
158 match self {
159 OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, ..), .. })
160 | OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig), .. })
161 | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig), .. })
162 | OwnerNode::ForeignItem(ForeignItem {
163 kind: ForeignItemKind::Fn(fn_sig, ..), ..
164 }) => Some(fn_sig),
165 _ => None,
166 }
167 }
168
169 pub fn generics(self) -> &'fhir Generics<'fhir> {
170 match self {
171 OwnerNode::Item(item) => &item.generics,
172 OwnerNode::TraitItem(trait_item) => &trait_item.generics,
173 OwnerNode::ImplItem(impl_item) => &impl_item.generics,
174 OwnerNode::ForeignItem(foreign_item) => {
175 match foreign_item.kind {
176 ForeignItemKind::Fn(_, generics) => generics,
177 }
178 }
179 }
180 }
181
182 pub fn owner_id(&self) -> MaybeExternId<OwnerId> {
183 match self {
184 OwnerNode::Item(item) => item.owner_id,
185 OwnerNode::TraitItem(trait_item) => trait_item.owner_id,
186 OwnerNode::ImplItem(impl_item) => impl_item.owner_id,
187 OwnerNode::ForeignItem(foreign_item) => foreign_item.owner_id,
188 }
189 }
190}
191
192#[derive(Debug)]
193pub struct Item<'fhir> {
194 pub owner_id: MaybeExternId<OwnerId>,
195 pub generics: Generics<'fhir>,
196 pub kind: ItemKind<'fhir>,
197}
198
199impl<'fhir> Item<'fhir> {
200 pub fn expect_enum(&self) -> &EnumDef<'fhir> {
201 if let ItemKind::Enum(enum_def) = &self.kind { enum_def } else { bug!("expected enum") }
202 }
203
204 pub fn expect_struct(&self) -> &StructDef<'fhir> {
205 if let ItemKind::Struct(struct_def) = &self.kind {
206 struct_def
207 } else {
208 bug!("expected struct")
209 }
210 }
211
212 pub fn expect_type_alias(&self) -> &TyAlias<'fhir> {
213 if let ItemKind::TyAlias(ty_alias) = &self.kind {
214 ty_alias
215 } else {
216 bug!("expected type alias")
217 }
218 }
219
220 pub fn expect_impl(&self) -> &Impl<'fhir> {
221 if let ItemKind::Impl(impl_) = &self.kind { impl_ } else { bug!("expected impl") }
222 }
223
224 pub fn expect_trait(&self) -> &Trait<'fhir> {
225 if let ItemKind::Trait(trait_) = &self.kind { trait_ } else { bug!("expected trait") }
226 }
227}
228
229#[derive(Debug)]
230pub enum ItemKind<'fhir> {
231 Enum(EnumDef<'fhir>),
232 Struct(StructDef<'fhir>),
233 TyAlias(TyAlias<'fhir>),
234 Trait(Trait<'fhir>),
235 Impl(Impl<'fhir>),
236 Fn(FnSig<'fhir>),
237 Const(Option<Expr<'fhir>>),
238}
239
240#[derive(Debug)]
241pub struct TraitItem<'fhir> {
242 pub owner_id: MaybeExternId<OwnerId>,
243 pub generics: Generics<'fhir>,
244 pub kind: TraitItemKind<'fhir>,
245}
246
247#[derive(Debug)]
248pub enum TraitItemKind<'fhir> {
249 Fn(FnSig<'fhir>),
250 Const,
251 Type,
252}
253
254#[derive(Debug)]
255pub struct ImplItem<'fhir> {
256 pub owner_id: MaybeExternId<OwnerId>,
257 pub kind: ImplItemKind<'fhir>,
258 pub generics: Generics<'fhir>,
259}
260
261#[derive(Debug)]
262pub enum ImplItemKind<'fhir> {
263 Fn(FnSig<'fhir>),
264 Const,
265 Type,
266}
267
268#[derive(Copy, Clone, Debug)]
269pub enum FluxItem<'fhir> {
270 Qualifier(&'fhir Qualifier<'fhir>),
271 Func(&'fhir SpecFunc<'fhir>),
272}
273
274impl FluxItem<'_> {
275 pub fn def_id(self) -> FluxLocalDefId {
276 match self {
277 FluxItem::Qualifier(qualifier) => qualifier.def_id,
278 FluxItem::Func(func) => func.def_id,
279 }
280 }
281}
282
283#[derive(Debug)]
284pub struct ForeignItem<'fhir> {
285 pub ident: Ident,
286 pub kind: ForeignItemKind<'fhir>,
287 pub owner_id: MaybeExternId<OwnerId>,
288 pub span: Span,
289}
290
291#[derive(Debug)]
292pub enum ForeignItemKind<'fhir> {
293 Fn(FnSig<'fhir>, &'fhir Generics<'fhir>),
294}
295
296#[derive(Debug, Clone, Copy)]
297pub struct SortDecl {
298 pub name: Symbol,
299 pub span: Span,
300}
301
302pub type SortDecls = FxHashMap<Symbol, SortDecl>;
303
304#[derive(Debug, Clone, Copy)]
305pub struct WhereBoundPredicate<'fhir> {
306 pub span: Span,
307 pub bounded_ty: Ty<'fhir>,
308 pub bounds: GenericBounds<'fhir>,
309}
310
311pub type GenericBounds<'fhir> = &'fhir [GenericBound<'fhir>];
312
313#[derive(Debug, Clone, Copy)]
314pub enum GenericBound<'fhir> {
315 Trait(PolyTraitRef<'fhir>),
316 Outlives(Lifetime),
317}
318
319#[derive(Debug, Clone, Copy)]
320pub struct PolyTraitRef<'fhir> {
321 pub bound_generic_params: &'fhir [GenericParam<'fhir>],
322 pub refine_params: &'fhir [RefineParam<'fhir>],
324 pub modifiers: TraitBoundModifier,
325 pub trait_ref: Path<'fhir>,
326 pub span: Span,
327}
328
329#[derive(Debug, Copy, Clone)]
330pub enum TraitBoundModifier {
331 None,
332 Maybe,
333}
334
335#[derive(Debug)]
336pub struct Trait<'fhir> {
337 pub assoc_refinements: &'fhir [TraitAssocReft<'fhir>],
338}
339
340impl<'fhir> Trait<'fhir> {
341 pub fn find_assoc_reft(&self, name: Symbol) -> Option<&'fhir TraitAssocReft<'fhir>> {
342 self.assoc_refinements
343 .iter()
344 .find(|assoc_reft| assoc_reft.name == name)
345 }
346}
347
348#[derive(Debug, Clone, Copy)]
349pub struct TraitAssocReft<'fhir> {
350 pub name: Symbol,
351 pub params: &'fhir [RefineParam<'fhir>],
352 pub output: Sort<'fhir>,
353 pub body: Option<Expr<'fhir>>,
354 pub span: Span,
355}
356
357#[derive(Debug)]
358pub struct Impl<'fhir> {
359 pub assoc_refinements: &'fhir [ImplAssocReft<'fhir>],
360}
361
362impl<'fhir> Impl<'fhir> {
363 pub fn find_assoc_reft(&self, name: Symbol) -> Option<&'fhir ImplAssocReft<'fhir>> {
364 self.assoc_refinements
365 .iter()
366 .find(|assoc_reft| assoc_reft.name == name)
367 }
368}
369
370#[derive(Clone, Copy, Debug)]
371pub struct ImplAssocReft<'fhir> {
372 pub name: Symbol,
373 pub params: &'fhir [RefineParam<'fhir>],
374 pub output: Sort<'fhir>,
375 pub body: Expr<'fhir>,
376 pub span: Span,
377}
378
379#[derive(Debug)]
380pub struct OpaqueTy<'fhir> {
381 pub def_id: MaybeExternId,
382 pub bounds: GenericBounds<'fhir>,
383}
384
385pub type Arena = bumpalo::Bump;
386
387#[derive(Default)]
392pub struct FluxItems<'fhir> {
393 pub items: FxIndexMap<FluxLocalDefId, FluxItem<'fhir>>,
394}
395
396impl FluxItems<'_> {
397 pub fn new() -> Self {
398 Self { items: Default::default() }
399 }
400}
401
402#[derive(Debug)]
403pub struct TyAlias<'fhir> {
404 pub index: Option<RefineParam<'fhir>>,
405 pub ty: Ty<'fhir>,
406 pub span: Span,
407 pub lifted: bool,
409}
410
411#[derive(Debug, Clone, Copy)]
412pub struct StructDef<'fhir> {
413 pub refinement: &'fhir RefinementKind<'fhir>,
414 pub params: &'fhir [RefineParam<'fhir>],
415 pub kind: StructKind<'fhir>,
416 pub invariants: &'fhir [Expr<'fhir>],
417}
418
419#[derive(Debug, Clone, Copy)]
420pub enum StructKind<'fhir> {
421 Transparent { fields: &'fhir [FieldDef<'fhir>] },
422 Opaque,
423}
424
425#[derive(Debug, Clone, Copy)]
426pub struct FieldDef<'fhir> {
427 pub ty: Ty<'fhir>,
428 pub lifted: bool,
430}
431
432#[derive(Debug)]
433pub enum RefinementKind<'fhir> {
434 Refined(RefinedBy<'fhir>),
436 Reflected,
438}
439
440impl RefinementKind<'_> {
441 pub fn is_reflected(&self) -> bool {
442 matches!(self, RefinementKind::Reflected)
443 }
444}
445
446#[derive(Debug)]
447pub struct EnumDef<'fhir> {
448 pub refinement: &'fhir RefinementKind<'fhir>,
449 pub params: &'fhir [RefineParam<'fhir>],
450 pub variants: &'fhir [VariantDef<'fhir>],
451 pub invariants: &'fhir [Expr<'fhir>],
452}
453
454#[derive(Debug, Clone, Copy)]
455pub struct VariantDef<'fhir> {
456 pub def_id: LocalDefId,
457 pub params: &'fhir [RefineParam<'fhir>],
458 pub fields: &'fhir [FieldDef<'fhir>],
459 pub ret: VariantRet<'fhir>,
460 pub span: Span,
461 pub lifted: bool,
463}
464
465#[derive(Debug, Clone, Copy)]
466pub struct VariantRet<'fhir> {
467 pub enum_id: DefId,
468 pub idx: Expr<'fhir>,
469}
470
471#[derive(Clone, Copy)]
472pub struct FnDecl<'fhir> {
473 pub requires: &'fhir [Requires<'fhir>],
474 pub inputs: &'fhir [Ty<'fhir>],
475 pub output: FnOutput<'fhir>,
476 pub span: Span,
477 pub lifted: bool,
479}
480
481#[derive(Clone, Copy)]
483pub struct Requires<'fhir> {
484 pub params: &'fhir [RefineParam<'fhir>],
486 pub pred: Expr<'fhir>,
487}
488
489#[derive(Clone, Copy)]
490pub struct FnSig<'fhir> {
491 pub header: FnHeader,
492 pub qualifiers: &'fhir [FluxLocalDefId],
494 pub reveals: &'fhir [FluxDefId],
496 pub decl: &'fhir FnDecl<'fhir>,
497}
498
499#[derive(Clone, Copy)]
500pub struct FnOutput<'fhir> {
501 pub params: &'fhir [RefineParam<'fhir>],
502 pub ret: Ty<'fhir>,
503 pub ensures: &'fhir [Ensures<'fhir>],
504}
505
506#[derive(Clone, Copy)]
507pub enum Ensures<'fhir> {
508 Type(PathExpr<'fhir>, Ty<'fhir>),
510 Pred(Expr<'fhir>),
512}
513
514#[derive(Clone, Copy)]
515pub struct Ty<'fhir> {
516 pub kind: TyKind<'fhir>,
517 pub span: Span,
518}
519
520#[derive(Clone, Copy)]
521pub enum TyKind<'fhir> {
522 BaseTy(BaseTy<'fhir>),
531 Indexed(BaseTy<'fhir>, Expr<'fhir>),
532 Exists(&'fhir [RefineParam<'fhir>], &'fhir Ty<'fhir>),
533 Constr(Expr<'fhir>, &'fhir Ty<'fhir>),
536 StrgRef(Lifetime, &'fhir PathExpr<'fhir>, &'fhir Ty<'fhir>),
537 Ref(Lifetime, MutTy<'fhir>),
538 BareFn(&'fhir BareFnTy<'fhir>),
539 Tuple(&'fhir [Ty<'fhir>]),
540 Array(&'fhir Ty<'fhir>, ConstArg),
541 RawPtr(&'fhir Ty<'fhir>, Mutability),
542 OpaqueDef(&'fhir OpaqueTy<'fhir>),
543 TraitObject(&'fhir [PolyTraitRef<'fhir>], Lifetime, TraitObjectSyntax),
544 Never,
545 Infer,
546 Err(ErrorGuaranteed),
547}
548
549pub struct BareFnTy<'fhir> {
550 pub safety: Safety,
551 pub abi: rustc_abi::ExternAbi,
552 pub generic_params: &'fhir [GenericParam<'fhir>],
553 pub decl: &'fhir FnDecl<'fhir>,
554 pub param_names: &'fhir [Ident],
555}
556
557#[derive(Clone, Copy)]
558pub struct MutTy<'fhir> {
559 pub ty: &'fhir Ty<'fhir>,
560 pub mutbl: Mutability,
561}
562
563#[derive(Copy, Clone, PartialEq, Eq)]
566pub enum Lifetime {
567 Hole(FhirId),
569 Resolved(ResolvedArg),
571}
572
573#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Encodable, Decodable)]
575pub enum FluxOwnerId {
576 Flux(FluxLocalDefId),
577 Rust(OwnerId),
578}
579
580impl FluxOwnerId {
581 pub fn def_id(self) -> Option<LocalDefId> {
582 match self {
583 FluxOwnerId::Flux(_) => None,
584 FluxOwnerId::Rust(owner_id) => Some(owner_id.def_id),
585 }
586 }
587}
588
589#[derive(Debug, Hash, PartialEq, Eq, Copy, Clone, Encodable, Decodable)]
597pub struct FhirId {
598 pub owner: FluxOwnerId,
599 pub local_id: ItemLocalId,
600}
601
602newtype_index! {
603 #[encodable]
605 pub struct ItemLocalId {}
606}
607
608#[derive(Clone, Copy)]
610pub struct BaseTy<'fhir> {
611 pub kind: BaseTyKind<'fhir>,
612 pub fhir_id: FhirId,
613 pub span: Span,
614}
615
616impl<'fhir> BaseTy<'fhir> {
617 pub fn from_qpath(qpath: QPath<'fhir>, fhir_id: FhirId) -> Self {
618 let span = qpath.span();
619 Self { kind: BaseTyKind::Path(qpath), fhir_id, span }
620 }
621
622 fn as_path(&self) -> Option<Path<'fhir>> {
623 match self.kind {
624 BaseTyKind::Path(QPath::Resolved(None, path)) => Some(path),
625 _ => None,
626 }
627 }
628}
629
630#[derive(Clone, Copy)]
631pub enum BaseTyKind<'fhir> {
632 Path(QPath<'fhir>),
633 Slice(&'fhir Ty<'fhir>),
634 Err(ErrorGuaranteed),
635}
636
637#[derive(Clone, Copy)]
638pub enum QPath<'fhir> {
639 Resolved(Option<&'fhir Ty<'fhir>>, Path<'fhir>),
640 TypeRelative(&'fhir Ty<'fhir>, &'fhir PathSegment<'fhir>),
641}
642
643#[derive(Clone, Copy)]
644pub struct Path<'fhir> {
645 pub res: Res,
646 pub fhir_id: FhirId,
647 pub segments: &'fhir [PathSegment<'fhir>],
648 pub refine: &'fhir [Expr<'fhir>],
649 pub span: Span,
650}
651
652impl<'fhir> Path<'fhir> {
653 pub fn last_segment(&self) -> &'fhir PathSegment<'fhir> {
654 self.segments.last().unwrap()
655 }
656}
657
658#[derive(Clone, Copy)]
659pub struct PathSegment<'fhir> {
660 pub ident: Ident,
661 pub res: Res,
662 pub args: &'fhir [GenericArg<'fhir>],
663 pub constraints: &'fhir [AssocItemConstraint<'fhir>],
664}
665
666#[derive(Clone, Copy)]
667pub struct AssocItemConstraint<'fhir> {
668 pub ident: Ident,
669 pub kind: AssocItemConstraintKind<'fhir>,
670}
671
672#[derive(Clone, Copy)]
673pub enum AssocItemConstraintKind<'fhir> {
674 Equality { term: Ty<'fhir> },
675}
676
677#[derive(Clone, Copy)]
678pub enum GenericArg<'fhir> {
679 Lifetime(Lifetime),
680 Type(&'fhir Ty<'fhir>),
681 Const(ConstArg),
682 Infer,
683}
684
685impl<'fhir> GenericArg<'fhir> {
686 pub fn expect_type(&self) -> &'fhir Ty<'fhir> {
687 if let GenericArg::Type(ty) = self { ty } else { bug!("expected `GenericArg::Type`") }
688 }
689}
690
691#[derive(PartialEq, Eq, Clone, Copy)]
692pub struct ConstArg {
693 pub kind: ConstArgKind,
694 pub span: Span,
695}
696
697#[derive(PartialEq, Eq, Clone, Copy)]
698pub enum ConstArgKind {
699 Lit(usize),
700 Param(DefId),
701 Infer,
702}
703
704#[derive(Eq, PartialEq, Debug, Copy, Clone)]
705pub enum Res {
706 Def(DefKind, DefId),
707 PrimTy(PrimTy),
708 SelfTyAlias { alias_to: DefId, is_trait_impl: bool },
709 SelfTyParam { trait_: DefId },
710 Err,
711}
712
713#[derive(Copy, Clone, Debug)]
715pub struct PartialRes {
716 base_res: Res,
717 unresolved_segments: usize,
718}
719
720impl PartialRes {
721 pub fn new(base_res: Res) -> Self {
722 Self { base_res, unresolved_segments: 0 }
723 }
724
725 pub fn with_unresolved_segments(base_res: Res, unresolved_segments: usize) -> Self {
726 Self { base_res, unresolved_segments }
727 }
728
729 #[inline]
730 pub fn base_res(&self) -> Res {
731 self.base_res
732 }
733
734 pub fn unresolved_segments(&self) -> usize {
735 self.unresolved_segments
736 }
737
738 #[inline]
739 pub fn full_res(&self) -> Option<Res> {
740 (self.unresolved_segments == 0).then_some(self.base_res)
741 }
742
743 #[inline]
744 pub fn expect_full_res(&self) -> Res {
745 self.full_res().unwrap_or_else(|| bug!("expected full res"))
746 }
747
748 pub fn is_box(&self, tcx: TyCtxt) -> bool {
749 self.full_res().is_some_and(|res| res.is_box(tcx))
750 }
751}
752
753#[derive(Debug, Clone, Copy)]
754pub struct RefineParam<'fhir> {
755 pub id: ParamId,
756 pub name: Symbol,
757 pub span: Span,
758 pub sort: Sort<'fhir>,
759 pub kind: ParamKind,
760 pub fhir_id: FhirId,
761}
762
763#[derive(PartialEq, Eq, Debug, Clone, Copy)]
765pub enum ParamKind {
766 Explicit(Option<ParamMode>),
768 At,
770 Pound,
772 Colon,
774 Loc,
776 Error,
787}
788
789impl ParamKind {
790 pub fn is_loc(&self) -> bool {
791 matches!(self, ParamKind::Loc)
792 }
793}
794
795#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable)]
797pub enum InferMode {
798 EVar,
802 KVar,
806}
807
808impl InferMode {
809 pub fn from_param_kind(kind: ParamKind) -> InferMode {
810 if let ParamKind::Explicit(Some(ParamMode::Horn)) = kind {
811 InferMode::KVar
812 } else {
813 InferMode::EVar
814 }
815 }
816
817 pub fn prefix_str(self) -> &'static str {
818 match self {
819 InferMode::EVar => "?",
820 InferMode::KVar => "$",
821 }
822 }
823}
824
825#[derive(Clone, Copy)]
826pub enum PrimSort {
827 Int,
828 Bool,
829 Real,
830 Set,
831 Map,
832}
833
834impl PrimSort {
835 pub fn name_str(self) -> &'static str {
836 match self {
837 PrimSort::Int => "int",
838 PrimSort::Bool => "bool",
839 PrimSort::Real => "real",
840 PrimSort::Set => "Set",
841 PrimSort::Map => "Map",
842 }
843 }
844
845 pub fn generics(self) -> usize {
847 match self {
848 PrimSort::Int => 0,
849 PrimSort::Bool => 0,
850 PrimSort::Real => 0,
851 PrimSort::Set => 1,
852 PrimSort::Map => 2,
853 }
854 }
855}
856
857#[derive(Clone, Copy)]
858pub enum SortRes {
859 PrimSort(PrimSort),
861 User { name: Symbol },
863 SortParam(usize),
865 TyParam(DefId),
867 SelfParam {
869 trait_id: DefId,
871 },
872 SelfAlias {
874 alias_to: DefId,
876 },
877 SelfParamAssoc { trait_id: DefId, ident: Ident },
886 Adt(DefId),
888}
889
890#[derive(Clone, Copy)]
891pub enum Sort<'fhir> {
892 Path(SortPath<'fhir>),
893 Loc,
895 BitVec(u32),
897 Func(PolyFuncSort<'fhir>),
899 SortOf(BaseTy<'fhir>),
902 Infer,
904 Err(ErrorGuaranteed),
905}
906
907#[derive(Clone, Copy)]
909pub struct SortPath<'fhir> {
910 pub res: SortRes,
911 pub segments: &'fhir [Ident],
912 pub args: &'fhir [Sort<'fhir>],
913}
914
915#[derive(Clone, Copy)]
916pub struct FuncSort<'fhir> {
917 pub inputs_and_output: &'fhir [Sort<'fhir>],
919}
920
921#[derive(Clone, Copy)]
922pub struct PolyFuncSort<'fhir> {
923 pub params: usize,
924 pub fsort: FuncSort<'fhir>,
925}
926
927impl<'fhir> PolyFuncSort<'fhir> {
928 pub fn new(params: usize, inputs_and_output: &'fhir [Sort]) -> Self {
929 let fsort = FuncSort { inputs_and_output };
930 Self { params, fsort }
931 }
932}
933
934#[derive(Clone, Copy)]
936pub struct AliasReft<'fhir> {
937 pub qself: &'fhir Ty<'fhir>,
938 pub path: Path<'fhir>,
939 pub name: Symbol,
940}
941
942#[derive(Debug, Clone, Copy)]
943pub struct FieldExpr<'fhir> {
944 pub ident: Ident,
945 pub expr: Expr<'fhir>,
946 pub fhir_id: FhirId,
947 pub span: Span,
948}
949
950#[derive(Debug, Clone, Copy)]
951pub struct Spread<'fhir> {
952 pub expr: Expr<'fhir>,
953 pub span: Span,
954 pub fhir_id: FhirId,
955}
956
957#[derive(Clone, Copy)]
958pub struct Expr<'fhir> {
959 pub kind: ExprKind<'fhir>,
960 pub fhir_id: FhirId,
961 pub span: Span,
962}
963
964#[derive(Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable)]
965pub enum QuantKind {
966 Forall,
967 Exists,
968}
969
970#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encodable, Decodable)]
971pub struct Range {
972 pub start: usize,
973 pub end: usize,
974}
975
976#[derive(Clone, Copy)]
977pub enum ExprKind<'fhir> {
978 Var(PathExpr<'fhir>, Option<ParamKind>),
979 Dot(&'fhir Expr<'fhir>, Ident),
980 Literal(Lit),
981 BinaryOp(BinOp, &'fhir Expr<'fhir>, &'fhir Expr<'fhir>),
982 UnaryOp(UnOp, &'fhir Expr<'fhir>),
983 App(PathExpr<'fhir>, &'fhir [Expr<'fhir>]),
984 Alias(AliasReft<'fhir>, &'fhir [Expr<'fhir>]),
985 IfThenElse(&'fhir Expr<'fhir>, &'fhir Expr<'fhir>, &'fhir Expr<'fhir>),
986 Abs(&'fhir [RefineParam<'fhir>], &'fhir Expr<'fhir>),
987 BoundedQuant(QuantKind, RefineParam<'fhir>, Range, &'fhir Expr<'fhir>),
988 Record(&'fhir [Expr<'fhir>]),
989 Constructor(Option<PathExpr<'fhir>>, &'fhir [FieldExpr<'fhir>], Option<&'fhir Spread<'fhir>>),
990 Block(&'fhir [LetDecl<'fhir>], &'fhir Expr<'fhir>),
991 Err(ErrorGuaranteed),
992}
993
994#[derive(Clone, Copy)]
995pub struct LetDecl<'fhir> {
996 pub param: RefineParam<'fhir>,
997 pub init: Expr<'fhir>,
998}
999
1000impl Expr<'_> {
1001 pub fn is_colon_param(&self) -> Option<ParamId> {
1002 if let ExprKind::Var(path, Some(ParamKind::Colon)) = &self.kind
1003 && let ExprRes::Param(kind, id) = path.res
1004 {
1005 debug_assert_eq!(kind, ParamKind::Colon);
1006 Some(id)
1007 } else {
1008 None
1009 }
1010 }
1011}
1012
1013#[derive(Clone, Copy)]
1014pub enum Lit {
1015 Int(u128),
1016 Real(u128),
1017 Bool(bool),
1018 Str(Symbol),
1019 Char(char),
1020}
1021
1022#[derive(Clone, Copy, Debug)]
1023pub enum ExprRes<Id = ParamId> {
1024 Param(ParamKind, Id),
1025 Const(DefId),
1026 Ctor(DefId),
1030 Variant(DefId),
1031 ConstGeneric(DefId),
1032 NumConst(i128),
1033 GlobalFunc(SpecFuncKind),
1034}
1035
1036impl<Id> ExprRes<Id> {
1037 pub fn map_param_id<R>(self, f: impl FnOnce(Id) -> R) -> ExprRes<R> {
1038 match self {
1039 ExprRes::Param(kind, param_id) => ExprRes::Param(kind, f(param_id)),
1040 ExprRes::Const(def_id) => ExprRes::Const(def_id),
1041 ExprRes::NumConst(val) => ExprRes::NumConst(val),
1042 ExprRes::GlobalFunc(kind) => ExprRes::GlobalFunc(kind),
1043 ExprRes::ConstGeneric(def_id) => ExprRes::ConstGeneric(def_id),
1044 ExprRes::Ctor(def_id) => ExprRes::Ctor(def_id),
1045 ExprRes::Variant(def_id) => ExprRes::Variant(def_id),
1046 }
1047 }
1048
1049 pub fn expect_param(self) -> (ParamKind, Id) {
1050 if let ExprRes::Param(kind, id) = self { (kind, id) } else { bug!("expected param") }
1051 }
1052}
1053
1054#[derive(Clone, Copy)]
1055pub struct PathExpr<'fhir> {
1056 pub segments: &'fhir [Ident],
1057 pub res: ExprRes,
1058 pub fhir_id: FhirId,
1059 pub span: Span,
1060}
1061
1062newtype_index! {
1063 #[debug_format = "a{}"]
1064 pub struct ParamId {}
1065}
1066
1067impl PolyTraitRef<'_> {
1068 pub fn trait_def_id(&self) -> DefId {
1069 let path = &self.trait_ref;
1070 if let Res::Def(DefKind::Trait, did) = path.res {
1071 did
1072 } else {
1073 span_bug!(path.span, "unexpected resolution {:?}", path.res);
1074 }
1075 }
1076}
1077
1078impl From<OwnerId> for FluxOwnerId {
1079 fn from(owner_id: OwnerId) -> Self {
1080 FluxOwnerId::Rust(owner_id)
1081 }
1082}
1083
1084impl<'fhir> Ty<'fhir> {
1085 pub fn as_path(&self) -> Option<Path<'fhir>> {
1086 match &self.kind {
1087 TyKind::BaseTy(bty) => bty.as_path(),
1088 _ => None,
1089 }
1090 }
1091}
1092
1093impl Res {
1094 pub fn descr(&self) -> &'static str {
1095 match self {
1096 Res::PrimTy(_) => "builtin type",
1097 Res::Def(kind, def_id) => kind.descr(*def_id),
1098 Res::SelfTyAlias { .. } | Res::SelfTyParam { .. } => "self type",
1099 Res::Err => "unresolved item",
1100 }
1101 }
1102
1103 pub fn is_box(&self, tcx: TyCtxt) -> bool {
1104 if let Res::Def(DefKind::Struct, def_id) = self {
1105 tcx.adt_def(def_id).is_box()
1106 } else {
1107 false
1108 }
1109 }
1110}
1111
1112impl<Id> TryFrom<rustc_hir::def::Res<Id>> for Res {
1113 type Error = ();
1114
1115 fn try_from(res: rustc_hir::def::Res<Id>) -> Result<Self, Self::Error> {
1116 match res {
1117 rustc_hir::def::Res::Def(kind, did) => Ok(Res::Def(kind, did)),
1118 rustc_hir::def::Res::PrimTy(prim_ty) => Ok(Res::PrimTy(prim_ty)),
1119 rustc_hir::def::Res::SelfTyAlias { alias_to, forbid_generic: false, is_trait_impl } => {
1120 Ok(Res::SelfTyAlias { alias_to, is_trait_impl })
1121 }
1122 rustc_hir::def::Res::SelfTyParam { trait_ } => Ok(Res::SelfTyParam { trait_ }),
1123 rustc_hir::def::Res::Err => Ok(Res::Err),
1124 _ => Err(()),
1125 }
1126 }
1127}
1128
1129impl QPath<'_> {
1130 pub fn span(&self) -> Span {
1131 match self {
1132 QPath::Resolved(_, path) => path.span,
1133 QPath::TypeRelative(qself, assoc) => qself.span.to(assoc.ident.span),
1134 }
1135 }
1136}
1137
1138impl Lit {
1139 pub const TRUE: Lit = Lit::Bool(true);
1140}
1141
1142#[derive(Clone, Debug)]
1144pub struct RefinedBy<'fhir> {
1145 pub sort_params: FxIndexSet<DefId>,
1160 pub fields: FxIndexMap<Symbol, Sort<'fhir>>,
1162}
1163
1164#[derive(Debug)]
1165pub struct SpecFunc<'fhir> {
1166 pub def_id: FluxLocalDefId,
1167 pub params: usize,
1168 pub args: &'fhir [RefineParam<'fhir>],
1169 pub sort: Sort<'fhir>,
1170 pub body: Option<Expr<'fhir>>,
1171 pub hide: bool,
1172}
1173
1174#[derive(Debug, Clone, Copy, Encodable, Decodable, PartialEq, Eq, Hash)]
1175pub enum SpecFuncKind {
1176 Thy(liquid_fixpoint::ThyFunc),
1178 Uif(FluxDefId),
1180 Def(FluxDefId),
1182}
1183
1184impl SpecFuncKind {
1185 pub fn def_id(&self) -> Option<FluxDefId> {
1186 match self {
1187 SpecFuncKind::Thy(_) => None,
1188 SpecFuncKind::Uif(flux_id) | SpecFuncKind::Def(flux_id) => Some(*flux_id),
1189 }
1190 }
1191}
1192
1193impl<'fhir> Generics<'fhir> {
1194 pub fn get_param(&self, def_id: LocalDefId) -> &'fhir GenericParam<'fhir> {
1195 self.params
1196 .iter()
1197 .find(|p| p.def_id.local_id() == def_id)
1198 .unwrap()
1199 }
1200}
1201
1202impl<'fhir> RefinedBy<'fhir> {
1203 pub fn new(fields: FxIndexMap<Symbol, Sort<'fhir>>, sort_params: FxIndexSet<DefId>) -> Self {
1204 RefinedBy { sort_params, fields }
1205 }
1206
1207 pub fn trivial() -> Self {
1208 RefinedBy { sort_params: Default::default(), fields: Default::default() }
1209 }
1210}
1211
1212impl<'fhir> From<PolyFuncSort<'fhir>> for Sort<'fhir> {
1213 fn from(fsort: PolyFuncSort<'fhir>) -> Self {
1214 Self::Func(fsort)
1215 }
1216}
1217
1218impl FuncSort<'_> {
1219 pub fn inputs(&self) -> &[Sort] {
1220 &self.inputs_and_output[..self.inputs_and_output.len() - 1]
1221 }
1222
1223 pub fn output(&self) -> &Sort {
1224 &self.inputs_and_output[self.inputs_and_output.len() - 1]
1225 }
1226}
1227
1228impl rustc_errors::IntoDiagArg for Ty<'_> {
1229 fn into_diag_arg(self, _path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
1230 rustc_errors::DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
1231 }
1232}
1233
1234impl rustc_errors::IntoDiagArg for Path<'_> {
1235 fn into_diag_arg(self, _path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
1236 rustc_errors::DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
1237 }
1238}
1239
1240impl StructDef<'_> {
1241 pub fn is_opaque(&self) -> bool {
1242 matches!(self.kind, StructKind::Opaque)
1243 }
1244}
1245
1246impl fmt::Debug for FnSig<'_> {
1247 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1248 write!(f, "{:?}", self.decl)
1249 }
1250}
1251
1252impl fmt::Debug for FnDecl<'_> {
1253 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1254 if !self.requires.is_empty() {
1255 write!(f, "[{:?}] ", self.requires.iter().format(", "))?;
1256 }
1257 write!(f, "fn({:?}) -> {:?}", self.inputs.iter().format(", "), self.output)
1258 }
1259}
1260
1261impl fmt::Debug for FnOutput<'_> {
1262 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1263 if !self.params.is_empty() {
1264 write!(
1265 f,
1266 "exists<{}> ",
1267 self.params.iter().format_with(", ", |param, f| {
1268 f(&format_args!("{}: {:?}", param.name, param.sort))
1269 })
1270 )?;
1271 }
1272 write!(f, "{:?}", self.ret)?;
1273 if !self.ensures.is_empty() {
1274 write!(f, "; [{:?}]", self.ensures.iter().format(", "))?;
1275 }
1276
1277 Ok(())
1278 }
1279}
1280
1281impl fmt::Debug for Requires<'_> {
1282 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1283 if !self.params.is_empty() {
1284 write!(
1285 f,
1286 "forall {}.",
1287 self.params.iter().format_with(",", |param, f| {
1288 f(&format_args!("{}:{:?}", param.name, param.sort))
1289 })
1290 )?;
1291 }
1292 write!(f, "{:?}", self.pred)
1293 }
1294}
1295
1296impl fmt::Debug for Ensures<'_> {
1297 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1298 match self {
1299 Ensures::Type(loc, ty) => write!(f, "{loc:?}: {ty:?}"),
1300 Ensures::Pred(e) => write!(f, "{e:?}"),
1301 }
1302 }
1303}
1304
1305impl fmt::Debug for Ty<'_> {
1306 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1307 match &self.kind {
1308 TyKind::BaseTy(bty) => write!(f, "{bty:?}"),
1309 TyKind::Indexed(bty, idx) => write!(f, "{bty:?}[{idx:?}]"),
1310 TyKind::Exists(params, ty) => {
1311 write!(f, "{{")?;
1312 write!(
1313 f,
1314 "{}",
1315 params.iter().format_with(",", |param, f| {
1316 f(&format_args!("{}:{:?}", param.name, param.sort))
1317 })
1318 )?;
1319 if let TyKind::Constr(pred, ty) = &ty.kind {
1320 write!(f, ". {ty:?} | {pred:?}}}")
1321 } else {
1322 write!(f, ". {ty:?}}}")
1323 }
1324 }
1325 TyKind::StrgRef(_lft, loc, ty) => write!(f, "&strg <{loc:?}: {ty:?}>"),
1326 TyKind::Ref(_lft, mut_ty) => {
1327 write!(f, "&{}{:?}", mut_ty.mutbl.prefix_str(), mut_ty.ty)
1328 }
1329 TyKind::BareFn(bare_fn_ty) => {
1330 write!(f, "{bare_fn_ty:?}")
1331 }
1332 TyKind::Tuple(tys) => write!(f, "({:?})", tys.iter().format(", ")),
1333 TyKind::Array(ty, len) => write!(f, "[{ty:?}; {len:?}]"),
1334 TyKind::Never => write!(f, "!"),
1335 TyKind::Constr(pred, ty) => write!(f, "{{{ty:?} | {pred:?}}}"),
1336 TyKind::RawPtr(ty, Mutability::Not) => write!(f, "*const {ty:?}"),
1337 TyKind::RawPtr(ty, Mutability::Mut) => write!(f, "*mut {ty:?}"),
1338 TyKind::Infer => write!(f, "_"),
1339 TyKind::OpaqueDef(opaque_ty) => {
1340 write!(f, "impl trait <def_id = {:?}>", opaque_ty.def_id.resolved_id(),)
1341 }
1342 TyKind::TraitObject(poly_traits, _lft, _syntax) => {
1343 write!(f, "dyn {poly_traits:?}")
1344 }
1345 TyKind::Err(_) => write!(f, "err"),
1346 }
1347 }
1348}
1349
1350impl fmt::Debug for BareFnTy<'_> {
1351 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1352 if !self.generic_params.is_empty() {
1353 write!(
1354 f,
1355 "for<{}>",
1356 self.generic_params
1357 .iter()
1358 .map(|param| param.name.ident())
1359 .format(",")
1360 )?;
1361 }
1362 write!(f, "{:?}", self.decl)
1363 }
1364}
1365
1366impl fmt::Debug for Lifetime {
1367 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1368 match self {
1369 Lifetime::Hole(_) => write!(f, "'_"),
1370 Lifetime::Resolved(lft) => write!(f, "{lft:?}"),
1371 }
1372 }
1373}
1374
1375impl fmt::Debug for ConstArg {
1376 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1377 write!(f, "{:?}", self.kind)
1378 }
1379}
1380
1381impl fmt::Debug for ConstArgKind {
1382 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1383 match self {
1384 ConstArgKind::Lit(n) => write!(f, "{n}"),
1385 ConstArgKind::Param(p) => write!(f, "{:?}", p),
1386 ConstArgKind::Infer => write!(f, "_"),
1387 }
1388 }
1389}
1390
1391impl fmt::Debug for BaseTy<'_> {
1392 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1393 match &self.kind {
1394 BaseTyKind::Path(qpath) => write!(f, "{qpath:?}"),
1395 BaseTyKind::Slice(ty) => write!(f, "[{ty:?}]"),
1396 BaseTyKind::Err(_) => write!(f, "err"),
1397 }
1398 }
1399}
1400
1401impl fmt::Debug for QPath<'_> {
1402 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1403 match self {
1404 QPath::Resolved(_, path) => write!(f, "{path:?}"),
1405 QPath::TypeRelative(qself, assoc) => write!(f, "<{qself:?}>::{assoc:?}"),
1406 }
1407 }
1408}
1409
1410impl fmt::Debug for Path<'_> {
1411 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1412 write!(f, "{:?}", self.segments.iter().format("::"))?;
1413 if !self.refine.is_empty() {
1414 write!(f, "({:?})", self.refine.iter().format(", "))?;
1415 }
1416 Ok(())
1417 }
1418}
1419
1420impl fmt::Debug for PathSegment<'_> {
1421 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1422 write!(f, "{}", self.ident)?;
1423 let args: Vec<_> = self
1424 .args
1425 .iter()
1426 .map(|a| a as &dyn std::fmt::Debug)
1427 .chain(self.constraints.iter().map(|b| b as &dyn std::fmt::Debug))
1428 .collect();
1429 if !args.is_empty() {
1430 write!(f, "<{:?}>", args.iter().format(", "))?;
1431 }
1432 Ok(())
1433 }
1434}
1435
1436impl fmt::Debug for GenericArg<'_> {
1437 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1438 match self {
1439 GenericArg::Type(ty) => write!(f, "{ty:?}"),
1440 GenericArg::Lifetime(lft) => write!(f, "{lft:?}"),
1441 GenericArg::Const(cst) => write!(f, "{cst:?}"),
1442 GenericArg::Infer => write!(f, "_"),
1443 }
1444 }
1445}
1446
1447impl fmt::Debug for AssocItemConstraint<'_> {
1448 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1449 match &self.kind {
1450 AssocItemConstraintKind::Equality { term } => {
1451 write!(f, "{:?} = {:?}", self.ident, term)
1452 }
1453 }
1454 }
1455}
1456
1457impl fmt::Debug for AliasReft<'_> {
1458 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1459 write!(f, "<{:?} as {:?}>::{}", self.qself, self.path, self.name)
1460 }
1461}
1462
1463impl fmt::Debug for QuantKind {
1464 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1465 match self {
1466 QuantKind::Forall => write!(f, "∀"),
1467 QuantKind::Exists => write!(f, "∃"),
1468 }
1469 }
1470}
1471
1472impl fmt::Debug for Expr<'_> {
1473 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1474 match self.kind {
1475 ExprKind::Var(x, ..) => write!(f, "{x:?}"),
1476 ExprKind::BinaryOp(op, e1, e2) => write!(f, "({e1:?} {op:?} {e2:?})"),
1477 ExprKind::UnaryOp(op, e) => write!(f, "{op:?}{e:?}"),
1478 ExprKind::Literal(lit) => write!(f, "{lit:?}"),
1479 ExprKind::App(uf, es) => write!(f, "{uf:?}({:?})", es.iter().format(", ")),
1480 ExprKind::Alias(alias, refine_args) => {
1481 write!(f, "{alias:?}({:?})", refine_args.iter().format(", "))
1482 }
1483 ExprKind::IfThenElse(p, e1, e2) => {
1484 write!(f, "(if {p:?} {{ {e1:?} }} else {{ {e2:?} }})")
1485 }
1486 ExprKind::Dot(var, fld) => write!(f, "{var:?}.{fld}"),
1487 ExprKind::Abs(params, body) => {
1488 write!(
1489 f,
1490 "|{}| {body:?}",
1491 params.iter().format_with(", ", |param, f| {
1492 f(&format_args!("{}: {:?}", param.name, param.sort))
1493 })
1494 )
1495 }
1496 ExprKind::Record(flds) => {
1497 write!(f, "{{ {:?} }}", flds.iter().format(", "))
1498 }
1499 ExprKind::Constructor(path, exprs, spread) => {
1500 if let Some(path) = path
1501 && let Some(s) = spread
1502 {
1503 write!(f, "{:?} {{ {:?}, ..{:?} }}", path, exprs.iter().format(", "), s)
1504 } else if let Some(path) = path {
1505 write!(f, "{:?} {{ {:?} }}", path, exprs.iter().format(", "))
1506 } else if let Some(s) = spread {
1507 write!(f, "{{ {:?} ..{:?} }}", exprs.iter().format(", "), s)
1508 } else {
1509 write!(f, "{{ {:?} }}", exprs.iter().format(", "))
1510 }
1511 }
1512 ExprKind::BoundedQuant(kind, refine_param, rng, expr) => {
1513 write!(f, "{kind:?} {refine_param:?} in {}.. {} {{ {expr:?} }}", rng.start, rng.end)
1514 }
1515 ExprKind::Err(_) => write!(f, "err"),
1516 ExprKind::Block(decls, body) => {
1517 for decl in decls {
1518 write!(f, "let {:?} = {:?};", decl.param, decl.init)?;
1519 }
1520 write!(f, "{body:?}")
1521 }
1522 }
1523 }
1524}
1525
1526impl fmt::Debug for PathExpr<'_> {
1527 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1528 write!(f, "{}", self.segments.iter().format("::"))
1529 }
1530}
1531
1532impl fmt::Debug for Lit {
1533 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1534 match self {
1535 Lit::Int(i) => write!(f, "{i}"),
1536 Lit::Real(r) => write!(f, "{r}real"),
1537 Lit::Bool(b) => write!(f, "{b}"),
1538 Lit::Str(s) => write!(f, "\"{s:?}\""),
1539 Lit::Char(c) => write!(f, "\'{c}\'"),
1540 }
1541 }
1542}
1543
1544impl fmt::Debug for Sort<'_> {
1545 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1546 match self {
1547 Sort::Path(path) => write!(f, "{path:?}"),
1548 Sort::BitVec(w) => write!(f, "bitvec({w})"),
1549 Sort::Loc => write!(f, "loc"),
1550 Sort::Func(fsort) => write!(f, "{fsort:?}"),
1551 Sort::SortOf(bty) => write!(f, "<{bty:?}>::sort"),
1552 Sort::Infer => write!(f, "_"),
1553 Sort::Err(_) => write!(f, "err"),
1554 }
1555 }
1556}
1557
1558impl fmt::Debug for SortPath<'_> {
1559 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1560 write!(f, "{:?}", self.res)?;
1561 if !self.args.is_empty() {
1562 write!(f, "<{:?}>", self.args.iter().format(", "))?;
1563 }
1564 Ok(())
1565 }
1566}
1567
1568impl fmt::Debug for SortRes {
1569 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1570 match self {
1571 SortRes::PrimSort(PrimSort::Bool) => write!(f, "bool"),
1572 SortRes::PrimSort(PrimSort::Int) => write!(f, "int"),
1573 SortRes::PrimSort(PrimSort::Real) => write!(f, "real"),
1574 SortRes::PrimSort(PrimSort::Set) => write!(f, "Set"),
1575 SortRes::PrimSort(PrimSort::Map) => write!(f, "Map"),
1576 SortRes::SortParam(n) => write!(f, "@{}", n),
1577 SortRes::TyParam(def_id) => write!(f, "{}::sort", def_id_to_string(*def_id)),
1578 SortRes::SelfParam { trait_id } => {
1579 write!(f, "{}::Self::sort", def_id_to_string(*trait_id))
1580 }
1581 SortRes::SelfAlias { alias_to } => {
1582 write!(f, "{}::Self::sort", def_id_to_string(*alias_to))
1583 }
1584 SortRes::SelfParamAssoc { ident: assoc, .. } => {
1585 write!(f, "Self::{assoc}")
1586 }
1587 SortRes::User { name } => write!(f, "{name}"),
1588 SortRes::Adt(def_id) => write!(f, "{}::sort", def_id_to_string(*def_id)),
1589 }
1590 }
1591}
1592
1593impl fmt::Debug for PolyFuncSort<'_> {
1594 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1595 if self.params > 0 {
1596 write!(f, "for<{}>{:?}", self.params, self.fsort)
1597 } else {
1598 write!(f, "{:?}", self.fsort)
1599 }
1600 }
1601}
1602
1603impl fmt::Debug for FuncSort<'_> {
1604 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1605 match self.inputs() {
1606 [input] => {
1607 write!(f, "{:?} -> {:?}", input, self.output())
1608 }
1609 inputs => {
1610 write!(f, "({:?}) -> {:?}", inputs.iter().format(", "), self.output())
1611 }
1612 }
1613 }
1614}