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, Namespace},
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(&'fhir 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 PrimOpProp(&'fhir PrimOpProp<'fhir>),
273}
274
275impl FluxItem<'_> {
276 pub fn def_id(self) -> FluxLocalDefId {
277 match self {
278 FluxItem::Qualifier(qualifier) => qualifier.def_id,
279 FluxItem::Func(func) => func.def_id,
280 FluxItem::PrimOpProp(prop) => prop.def_id,
281 }
282 }
283}
284
285#[derive(Debug)]
286pub struct ForeignItem<'fhir> {
287 pub ident: Ident,
288 pub kind: ForeignItemKind<'fhir>,
289 pub owner_id: MaybeExternId<OwnerId>,
290 pub span: Span,
291}
292
293#[derive(Debug)]
294pub enum ForeignItemKind<'fhir> {
295 Fn(FnSig<'fhir>, &'fhir Generics<'fhir>),
296}
297
298#[derive(Debug, Clone, Copy)]
299pub struct SortDecl {
300 pub name: Symbol,
301 pub span: Span,
302}
303
304pub type SortDecls = FxHashMap<Symbol, SortDecl>;
305
306#[derive(Debug, Clone, Copy)]
307pub struct WhereBoundPredicate<'fhir> {
308 pub span: Span,
309 pub bounded_ty: Ty<'fhir>,
310 pub bounds: GenericBounds<'fhir>,
311}
312
313pub type GenericBounds<'fhir> = &'fhir [GenericBound<'fhir>];
314
315#[derive(Debug, Clone, Copy)]
316pub enum GenericBound<'fhir> {
317 Trait(PolyTraitRef<'fhir>),
318 Outlives(Lifetime),
319}
320
321#[derive(Debug, Clone, Copy)]
322pub struct PolyTraitRef<'fhir> {
323 pub bound_generic_params: &'fhir [GenericParam<'fhir>],
324 pub refine_params: &'fhir [RefineParam<'fhir>],
326 pub modifiers: TraitBoundModifier,
327 pub trait_ref: Path<'fhir>,
328 pub span: Span,
329}
330
331#[derive(Debug, Copy, Clone)]
332pub enum TraitBoundModifier {
333 None,
334 Maybe,
335}
336
337#[derive(Debug)]
338pub struct Trait<'fhir> {
339 pub assoc_refinements: &'fhir [TraitAssocReft<'fhir>],
340}
341
342impl<'fhir> Trait<'fhir> {
343 pub fn find_assoc_reft(&self, name: Symbol) -> Option<&'fhir TraitAssocReft<'fhir>> {
344 self.assoc_refinements
345 .iter()
346 .find(|assoc_reft| assoc_reft.name == name)
347 }
348}
349
350#[derive(Debug, Clone, Copy)]
351pub struct TraitAssocReft<'fhir> {
352 pub name: Symbol,
353 pub params: &'fhir [RefineParam<'fhir>],
354 pub output: Sort<'fhir>,
355 pub body: Option<Expr<'fhir>>,
356 pub span: Span,
357 pub final_: bool,
358}
359
360#[derive(Debug)]
361pub struct Impl<'fhir> {
362 pub assoc_refinements: &'fhir [ImplAssocReft<'fhir>],
363}
364
365impl<'fhir> Impl<'fhir> {
366 pub fn find_assoc_reft(&self, name: Symbol) -> Option<&'fhir ImplAssocReft<'fhir>> {
367 self.assoc_refinements
368 .iter()
369 .find(|assoc_reft| assoc_reft.name == name)
370 }
371}
372
373#[derive(Clone, Copy, Debug)]
374pub struct ImplAssocReft<'fhir> {
375 pub name: Symbol,
376 pub params: &'fhir [RefineParam<'fhir>],
377 pub output: Sort<'fhir>,
378 pub body: Expr<'fhir>,
379 pub span: Span,
380}
381
382#[derive(Debug)]
383pub struct OpaqueTy<'fhir> {
384 pub def_id: MaybeExternId,
385 pub bounds: GenericBounds<'fhir>,
386}
387
388pub type Arena = bumpalo::Bump;
389
390#[derive(Default)]
395pub struct FluxItems<'fhir> {
396 pub items: FxIndexMap<FluxLocalDefId, FluxItem<'fhir>>,
397}
398
399impl FluxItems<'_> {
400 pub fn new() -> Self {
401 Self { items: Default::default() }
402 }
403}
404
405#[derive(Debug)]
406pub struct TyAlias<'fhir> {
407 pub index: Option<RefineParam<'fhir>>,
408 pub ty: Ty<'fhir>,
409 pub span: Span,
410 pub lifted: bool,
412}
413
414#[derive(Debug, Clone, Copy)]
415pub struct StructDef<'fhir> {
416 pub refinement: &'fhir RefinementKind<'fhir>,
417 pub params: &'fhir [RefineParam<'fhir>],
418 pub kind: StructKind<'fhir>,
419 pub invariants: &'fhir [Expr<'fhir>],
420}
421
422#[derive(Debug, Clone, Copy)]
423pub enum StructKind<'fhir> {
424 Transparent { fields: &'fhir [FieldDef<'fhir>] },
425 Opaque,
426}
427
428#[derive(Debug, Clone, Copy)]
429pub struct FieldDef<'fhir> {
430 pub ty: Ty<'fhir>,
431 pub lifted: bool,
433}
434
435#[derive(Debug)]
436pub enum RefinementKind<'fhir> {
437 Refined(RefinedBy<'fhir>),
439 Reflected,
441}
442
443impl RefinementKind<'_> {
444 pub fn is_reflected(&self) -> bool {
445 matches!(self, RefinementKind::Reflected)
446 }
447}
448
449#[derive(Debug)]
450pub struct EnumDef<'fhir> {
451 pub refinement: &'fhir RefinementKind<'fhir>,
452 pub params: &'fhir [RefineParam<'fhir>],
453 pub variants: &'fhir [VariantDef<'fhir>],
454 pub invariants: &'fhir [Expr<'fhir>],
455}
456
457#[derive(Debug, Clone, Copy)]
458pub struct VariantDef<'fhir> {
459 pub def_id: LocalDefId,
460 pub params: &'fhir [RefineParam<'fhir>],
461 pub fields: &'fhir [FieldDef<'fhir>],
462 pub ret: VariantRet<'fhir>,
463 pub span: Span,
464 pub lifted: bool,
466}
467
468#[derive(Debug, Clone, Copy)]
469pub struct VariantRet<'fhir> {
470 pub enum_id: DefId,
471 pub idx: Expr<'fhir>,
472}
473
474#[derive(Clone, Copy)]
475pub struct FnDecl<'fhir> {
476 pub requires: &'fhir [Requires<'fhir>],
477 pub inputs: &'fhir [Ty<'fhir>],
478 pub output: FnOutput<'fhir>,
479 pub span: Span,
480 pub lifted: bool,
482}
483
484#[derive(Clone, Copy)]
486pub struct Requires<'fhir> {
487 pub params: &'fhir [RefineParam<'fhir>],
489 pub pred: Expr<'fhir>,
490}
491
492#[derive(Clone, Copy)]
493pub struct FnSig<'fhir> {
494 pub header: FnHeader,
495 pub qualifiers: &'fhir [FluxLocalDefId],
497 pub reveals: &'fhir [FluxDefId],
499 pub decl: &'fhir FnDecl<'fhir>,
500}
501
502#[derive(Clone, Copy)]
503pub struct FnOutput<'fhir> {
504 pub params: &'fhir [RefineParam<'fhir>],
505 pub ret: Ty<'fhir>,
506 pub ensures: &'fhir [Ensures<'fhir>],
507}
508
509#[derive(Clone, Copy)]
510pub enum Ensures<'fhir> {
511 Type(PathExpr<'fhir>, &'fhir Ty<'fhir>),
513 Pred(Expr<'fhir>),
515}
516
517#[derive(Clone, Copy)]
518pub struct Ty<'fhir> {
519 pub kind: TyKind<'fhir>,
520 pub span: Span,
521}
522
523#[derive(Clone, Copy)]
524pub enum TyKind<'fhir> {
525 BaseTy(BaseTy<'fhir>),
534 Indexed(BaseTy<'fhir>, Expr<'fhir>),
535 Exists(&'fhir [RefineParam<'fhir>], &'fhir Ty<'fhir>),
536 Constr(Expr<'fhir>, &'fhir Ty<'fhir>),
539 StrgRef(Lifetime, &'fhir PathExpr<'fhir>, &'fhir Ty<'fhir>),
540 Ref(Lifetime, MutTy<'fhir>),
541 BareFn(&'fhir BareFnTy<'fhir>),
542 Tuple(&'fhir [Ty<'fhir>]),
543 Array(&'fhir Ty<'fhir>, ConstArg),
544 RawPtr(&'fhir Ty<'fhir>, Mutability),
545 OpaqueDef(&'fhir OpaqueTy<'fhir>),
546 TraitObject(&'fhir [PolyTraitRef<'fhir>], Lifetime, TraitObjectSyntax),
547 Never,
548 Infer,
549 Err(ErrorGuaranteed),
550}
551
552pub struct BareFnTy<'fhir> {
553 pub safety: Safety,
554 pub abi: rustc_abi::ExternAbi,
555 pub generic_params: &'fhir [GenericParam<'fhir>],
556 pub decl: &'fhir FnDecl<'fhir>,
557 pub param_idents: &'fhir [Option<Ident>],
558}
559
560#[derive(Clone, Copy)]
561pub struct MutTy<'fhir> {
562 pub ty: &'fhir Ty<'fhir>,
563 pub mutbl: Mutability,
564}
565
566#[derive(Copy, Clone, PartialEq, Eq)]
569pub enum Lifetime {
570 Hole(FhirId),
572 Resolved(ResolvedArg),
574}
575
576#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Encodable, Decodable)]
578pub enum FluxOwnerId {
579 Flux(FluxLocalDefId),
580 Rust(OwnerId),
581}
582
583impl FluxOwnerId {
584 pub fn def_id(self) -> Option<LocalDefId> {
585 match self {
586 FluxOwnerId::Flux(_) => None,
587 FluxOwnerId::Rust(owner_id) => Some(owner_id.def_id),
588 }
589 }
590}
591
592#[derive(Debug, Hash, PartialEq, Eq, Copy, Clone, Encodable, Decodable)]
600pub struct FhirId {
601 pub owner: FluxOwnerId,
602 pub local_id: ItemLocalId,
603}
604
605newtype_index! {
606 #[encodable]
608 pub struct ItemLocalId {}
609}
610
611#[derive(Clone, Copy)]
613pub struct BaseTy<'fhir> {
614 pub kind: BaseTyKind<'fhir>,
615 pub fhir_id: FhirId,
616 pub span: Span,
617}
618
619impl<'fhir> BaseTy<'fhir> {
620 pub fn from_qpath(qpath: QPath<'fhir>, fhir_id: FhirId) -> Self {
621 let span = qpath.span();
622 Self { kind: BaseTyKind::Path(qpath), fhir_id, span }
623 }
624
625 fn as_path(&self) -> Option<Path<'fhir>> {
626 match self.kind {
627 BaseTyKind::Path(QPath::Resolved(None, path)) => Some(path),
628 _ => None,
629 }
630 }
631}
632
633#[derive(Clone, Copy)]
634pub enum BaseTyKind<'fhir> {
635 Path(QPath<'fhir>),
636 Slice(&'fhir Ty<'fhir>),
637 Err(ErrorGuaranteed),
638}
639
640#[derive(Clone, Copy)]
641pub enum QPath<'fhir> {
642 Resolved(Option<&'fhir Ty<'fhir>>, Path<'fhir>),
643 TypeRelative(&'fhir Ty<'fhir>, &'fhir PathSegment<'fhir>),
644}
645
646#[derive(Clone, Copy)]
647pub struct Path<'fhir> {
648 pub res: Res,
649 pub fhir_id: FhirId,
650 pub segments: &'fhir [PathSegment<'fhir>],
651 pub refine: &'fhir [Expr<'fhir>],
652 pub span: Span,
653}
654
655impl<'fhir> Path<'fhir> {
656 pub fn last_segment(&self) -> &'fhir PathSegment<'fhir> {
657 self.segments.last().unwrap()
658 }
659}
660
661#[derive(Clone, Copy)]
662pub struct PathSegment<'fhir> {
663 pub ident: Ident,
664 pub res: Res,
665 pub args: &'fhir [GenericArg<'fhir>],
666 pub constraints: &'fhir [AssocItemConstraint<'fhir>],
667}
668
669#[derive(Clone, Copy)]
670pub struct AssocItemConstraint<'fhir> {
671 pub ident: Ident,
672 pub kind: AssocItemConstraintKind<'fhir>,
673}
674
675#[derive(Clone, Copy)]
676pub enum AssocItemConstraintKind<'fhir> {
677 Equality { term: Ty<'fhir> },
678}
679
680#[derive(Clone, Copy)]
681pub enum GenericArg<'fhir> {
682 Lifetime(Lifetime),
683 Type(&'fhir Ty<'fhir>),
684 Const(ConstArg),
685 Infer,
686}
687
688impl<'fhir> GenericArg<'fhir> {
689 pub fn expect_type(&self) -> &'fhir Ty<'fhir> {
690 if let GenericArg::Type(ty) = self { ty } else { bug!("expected `GenericArg::Type`") }
691 }
692}
693
694#[derive(PartialEq, Eq, Clone, Copy)]
695pub struct ConstArg {
696 pub kind: ConstArgKind,
697 pub span: Span,
698}
699
700#[derive(PartialEq, Eq, Clone, Copy)]
701pub enum ConstArgKind {
702 Lit(usize),
703 Param(DefId),
704 Infer,
705}
706
707#[derive(Eq, PartialEq, Debug, Copy, Clone)]
712pub enum Res<Id = !> {
713 Def(DefKind, DefId),
715 PrimTy(PrimTy),
717 SelfTyAlias {
719 alias_to: DefId,
720 is_trait_impl: bool,
721 },
722 SelfTyParam {
724 trait_: DefId,
725 },
726 Param(ParamKind, Id),
728 GlobalFunc(SpecFuncKind),
730 NumConst(i128),
732 Err,
733}
734
735#[derive(Copy, Clone, Debug)]
737pub struct PartialRes {
738 base_res: Res<!>,
739 unresolved_segments: usize,
740}
741
742impl PartialRes {
743 pub fn new(base_res: Res) -> Self {
744 Self { base_res, unresolved_segments: 0 }
745 }
746
747 pub fn with_unresolved_segments(base_res: Res, unresolved_segments: usize) -> Self {
748 Self { base_res, unresolved_segments }
749 }
750
751 #[inline]
752 pub fn base_res(&self) -> Res {
753 self.base_res
754 }
755
756 pub fn unresolved_segments(&self) -> usize {
757 self.unresolved_segments
758 }
759
760 #[inline]
761 pub fn full_res(&self) -> Option<Res> {
762 (self.unresolved_segments == 0).then_some(self.base_res)
763 }
764
765 #[inline]
766 pub fn expect_full_res(&self) -> Res {
767 self.full_res().unwrap_or_else(|| bug!("expected full res"))
768 }
769
770 pub fn is_box(&self, tcx: TyCtxt) -> bool {
771 self.full_res().is_some_and(|res| res.is_box(tcx))
772 }
773}
774
775#[derive(Debug, Clone, Copy)]
776pub struct RefineParam<'fhir> {
777 pub id: ParamId,
778 pub name: Symbol,
779 pub span: Span,
780 pub sort: Sort<'fhir>,
781 pub kind: ParamKind,
782 pub fhir_id: FhirId,
783}
784
785#[derive(PartialEq, Eq, Debug, Clone, Copy)]
787pub enum ParamKind {
788 Explicit(Option<ParamMode>),
790 At,
792 Pound,
794 Colon,
796 Loc,
798 Error,
809}
810
811impl ParamKind {
812 pub fn is_loc(&self) -> bool {
813 matches!(self, ParamKind::Loc)
814 }
815}
816
817#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable)]
819pub enum InferMode {
820 EVar,
824 KVar,
828}
829
830impl InferMode {
831 pub fn from_param_kind(kind: ParamKind) -> InferMode {
832 if let ParamKind::Explicit(Some(ParamMode::Horn)) = kind {
833 InferMode::KVar
834 } else {
835 InferMode::EVar
836 }
837 }
838
839 pub fn prefix_str(self) -> &'static str {
840 match self {
841 InferMode::EVar => "?",
842 InferMode::KVar => "$",
843 }
844 }
845}
846
847#[derive(Clone, Copy)]
848pub enum PrimSort {
849 Int,
850 Bool,
851 Char,
852 Real,
853 Set,
854 Map,
855 Str,
856}
857
858impl PrimSort {
859 pub fn name_str(self) -> &'static str {
860 match self {
861 PrimSort::Int => "int",
862 PrimSort::Str => "str",
863 PrimSort::Bool => "bool",
864 PrimSort::Char => "char",
865 PrimSort::Real => "real",
866 PrimSort::Set => "Set",
867 PrimSort::Map => "Map",
868 }
869 }
870
871 pub fn generics(self) -> usize {
873 match self {
874 PrimSort::Int | PrimSort::Bool | PrimSort::Real | PrimSort::Char | PrimSort::Str => 0,
875 PrimSort::Set => 1,
876 PrimSort::Map => 2,
877 }
878 }
879}
880
881#[derive(Clone, Copy)]
882pub enum SortRes {
883 PrimSort(PrimSort),
885 User { name: Symbol },
887 SortParam(usize),
889 TyParam(DefId),
891 SelfParam {
893 trait_id: DefId,
895 },
896 SelfAlias {
898 alias_to: DefId,
900 },
901 SelfParamAssoc { trait_id: DefId, ident: Ident },
910 Adt(DefId),
912}
913
914#[derive(Clone, Copy)]
915pub enum Sort<'fhir> {
916 Path(SortPath<'fhir>),
917 Loc,
919 BitVec(u32),
921 Func(PolyFuncSort<'fhir>),
923 SortOf(BaseTy<'fhir>),
926 Infer,
928 Err(ErrorGuaranteed),
929}
930
931#[derive(Clone, Copy)]
933pub struct SortPath<'fhir> {
934 pub res: SortRes,
935 pub segments: &'fhir [Ident],
936 pub args: &'fhir [Sort<'fhir>],
937}
938
939#[derive(Clone, Copy)]
940pub struct FuncSort<'fhir> {
941 pub inputs_and_output: &'fhir [Sort<'fhir>],
943}
944
945#[derive(Clone, Copy)]
946pub struct PolyFuncSort<'fhir> {
947 pub params: usize,
948 pub fsort: FuncSort<'fhir>,
949}
950
951impl<'fhir> PolyFuncSort<'fhir> {
952 pub fn new(params: usize, inputs_and_output: &'fhir [Sort]) -> Self {
953 let fsort = FuncSort { inputs_and_output };
954 Self { params, fsort }
955 }
956}
957
958#[derive(Clone, Copy)]
960pub struct AliasReft<'fhir> {
961 pub qself: &'fhir Ty<'fhir>,
962 pub path: Path<'fhir>,
963 pub name: Ident,
964}
965
966#[derive(Debug, Clone, Copy)]
967pub struct FieldExpr<'fhir> {
968 pub ident: Ident,
969 pub expr: Expr<'fhir>,
970 pub fhir_id: FhirId,
971 pub span: Span,
972}
973
974#[derive(Debug, Clone, Copy)]
975pub struct Spread<'fhir> {
976 pub expr: Expr<'fhir>,
977 pub span: Span,
978 pub fhir_id: FhirId,
979}
980
981#[derive(Clone, Copy)]
982pub struct Expr<'fhir> {
983 pub kind: ExprKind<'fhir>,
984 pub fhir_id: FhirId,
985 pub span: Span,
986}
987
988#[derive(Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable)]
989pub enum QuantKind {
990 Forall,
991 Exists,
992}
993
994#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encodable, Decodable)]
995pub struct Range {
996 pub start: usize,
997 pub end: usize,
998}
999
1000#[derive(Clone, Copy)]
1001pub enum ExprKind<'fhir> {
1002 Var(PathExpr<'fhir>, Option<ParamKind>),
1003 Dot(&'fhir Expr<'fhir>, Ident),
1004 Literal(Lit),
1005 BinaryOp(BinOp, &'fhir Expr<'fhir>, &'fhir Expr<'fhir>),
1006 UnaryOp(UnOp, &'fhir Expr<'fhir>),
1007 App(PathExpr<'fhir>, &'fhir [Expr<'fhir>]),
1008 PrimApp(BinOp, &'fhir Expr<'fhir>, &'fhir Expr<'fhir>),
1010 Alias(AliasReft<'fhir>, &'fhir [Expr<'fhir>]),
1011 IfThenElse(&'fhir Expr<'fhir>, &'fhir Expr<'fhir>, &'fhir Expr<'fhir>),
1012 Abs(&'fhir [RefineParam<'fhir>], &'fhir Expr<'fhir>),
1013 BoundedQuant(QuantKind, RefineParam<'fhir>, Range, &'fhir Expr<'fhir>),
1014 Record(&'fhir [Expr<'fhir>]),
1015 Constructor(Option<PathExpr<'fhir>>, &'fhir [FieldExpr<'fhir>], Option<&'fhir Spread<'fhir>>),
1016 Block(&'fhir [LetDecl<'fhir>], &'fhir Expr<'fhir>),
1017 Err(ErrorGuaranteed),
1018}
1019
1020#[derive(Clone, Copy)]
1021pub struct LetDecl<'fhir> {
1022 pub param: RefineParam<'fhir>,
1023 pub init: Expr<'fhir>,
1024}
1025
1026impl Expr<'_> {
1027 pub fn is_colon_param(&self) -> Option<ParamId> {
1028 if let ExprKind::Var(path, Some(ParamKind::Colon)) = &self.kind
1029 && let Res::Param(kind, id) = path.res
1030 {
1031 debug_assert_eq!(kind, ParamKind::Colon);
1032 Some(id)
1033 } else {
1034 None
1035 }
1036 }
1037}
1038
1039#[derive(Clone, Copy)]
1040pub enum NumLitKind {
1041 Int,
1042 Real,
1043}
1044
1045#[derive(Clone, Copy)]
1046pub enum Lit {
1047 Int(u128, Option<NumLitKind>),
1048 Bool(bool),
1049 Str(Symbol),
1050 Char(char),
1051}
1052
1053#[derive(Clone, Copy)]
1054pub struct PathExpr<'fhir> {
1055 pub segments: &'fhir [Ident],
1056 pub res: Res<ParamId>,
1057 pub fhir_id: FhirId,
1058 pub span: Span,
1059}
1060
1061newtype_index! {
1062 #[debug_format = "a{}"]
1063 pub struct ParamId {}
1064}
1065
1066impl PolyTraitRef<'_> {
1067 pub fn trait_def_id(&self) -> DefId {
1068 let path = &self.trait_ref;
1069 if let Res::Def(DefKind::Trait, did) = path.res {
1070 did
1071 } else {
1072 span_bug!(path.span, "unexpected resolution {:?}", path.res);
1073 }
1074 }
1075}
1076
1077impl From<OwnerId> for FluxOwnerId {
1078 fn from(owner_id: OwnerId) -> Self {
1079 FluxOwnerId::Rust(owner_id)
1080 }
1081}
1082
1083impl<'fhir> Ty<'fhir> {
1084 pub fn as_path(&self) -> Option<Path<'fhir>> {
1085 match &self.kind {
1086 TyKind::BaseTy(bty) => bty.as_path(),
1087 _ => None,
1088 }
1089 }
1090}
1091
1092impl<Id> Res<Id> {
1093 pub fn descr(&self) -> &'static str {
1094 match self {
1095 Res::PrimTy(_) => "builtin type",
1096 Res::Def(kind, def_id) => kind.descr(*def_id),
1097 Res::SelfTyAlias { .. } | Res::SelfTyParam { .. } => "self type",
1098 Res::Param(..) => "refinement parameter",
1099 Res::GlobalFunc(..) => "refinement function",
1100 Res::NumConst(_) => "numeric constant",
1101 Res::Err => "unresolved item",
1102 }
1103 }
1104
1105 pub fn is_box(&self, tcx: TyCtxt) -> bool {
1106 if let Res::Def(DefKind::Struct, def_id) = self {
1107 tcx.adt_def(def_id).is_box()
1108 } else {
1109 false
1110 }
1111 }
1112
1113 pub fn ns(&self) -> Option<Namespace> {
1115 match self {
1116 Res::Def(kind, ..) => kind.ns(),
1117 Res::PrimTy(..) | Res::SelfTyAlias { .. } | Res::SelfTyParam { .. } => {
1118 Some(Namespace::TypeNS)
1119 }
1120 Res::Param(..) | Res::GlobalFunc(..) | Res::NumConst(..) => Some(Namespace::ValueNS),
1121 Res::Err => None,
1122 }
1123 }
1124
1125 pub fn matches_ns(&self, ns: Namespace) -> bool {
1127 self.ns().is_none_or(|actual_ns| actual_ns == ns)
1128 }
1129
1130 pub fn map_param_id<R>(self, f: impl FnOnce(Id) -> R) -> Res<R> {
1131 match self {
1132 Res::Param(kind, param_id) => Res::Param(kind, f(param_id)),
1133 Res::Def(def_kind, def_id) => Res::Def(def_kind, def_id),
1134 Res::PrimTy(prim_ty) => Res::PrimTy(prim_ty),
1135 Res::SelfTyAlias { alias_to, is_trait_impl } => {
1136 Res::SelfTyAlias { alias_to, is_trait_impl }
1137 }
1138 Res::SelfTyParam { trait_ } => Res::SelfTyParam { trait_ },
1139 Res::GlobalFunc(spec_func_kind) => Res::GlobalFunc(spec_func_kind),
1140 Res::NumConst(val) => Res::NumConst(val),
1141 Res::Err => Res::Err,
1142 }
1143 }
1144
1145 pub fn expect_param(self) -> (ParamKind, Id) {
1146 if let Res::Param(kind, id) = self { (kind, id) } else { bug!("expected param") }
1147 }
1148}
1149
1150impl<Id1, Id2> TryFrom<rustc_hir::def::Res<Id1>> for Res<Id2> {
1151 type Error = ();
1152
1153 fn try_from(res: rustc_hir::def::Res<Id1>) -> Result<Self, Self::Error> {
1154 match res {
1155 rustc_hir::def::Res::Def(kind, did) => Ok(Res::Def(kind, did)),
1156 rustc_hir::def::Res::PrimTy(prim_ty) => Ok(Res::PrimTy(prim_ty)),
1157 rustc_hir::def::Res::SelfTyAlias { alias_to, forbid_generic: false, is_trait_impl } => {
1158 Ok(Res::SelfTyAlias { alias_to, is_trait_impl })
1159 }
1160 rustc_hir::def::Res::SelfTyParam { trait_ } => Ok(Res::SelfTyParam { trait_ }),
1161 rustc_hir::def::Res::Err => Ok(Res::Err),
1162 _ => Err(()),
1163 }
1164 }
1165}
1166
1167impl QPath<'_> {
1168 pub fn span(&self) -> Span {
1169 match self {
1170 QPath::Resolved(_, path) => path.span,
1171 QPath::TypeRelative(qself, assoc) => qself.span.to(assoc.ident.span),
1172 }
1173 }
1174}
1175
1176impl Lit {
1177 pub const TRUE: Lit = Lit::Bool(true);
1178}
1179
1180#[derive(Clone, Debug)]
1182pub struct RefinedBy<'fhir> {
1183 pub sort_params: FxIndexSet<DefId>,
1198 pub fields: FxIndexMap<Symbol, Sort<'fhir>>,
1200}
1201
1202#[derive(Debug)]
1203pub struct SpecFunc<'fhir> {
1204 pub def_id: FluxLocalDefId,
1205 pub params: usize,
1206 pub args: &'fhir [RefineParam<'fhir>],
1207 pub sort: Sort<'fhir>,
1208 pub body: Option<Expr<'fhir>>,
1209 pub hide: bool,
1210 pub ident_span: Span,
1211}
1212#[derive(Debug)]
1213pub struct PrimOpProp<'fhir> {
1214 pub def_id: FluxLocalDefId,
1215 pub op: BinOp,
1216 pub args: &'fhir [RefineParam<'fhir>],
1217 pub body: Expr<'fhir>,
1218 pub span: Span,
1219}
1220
1221#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1222pub enum SpecFuncKind {
1223 Thy(liquid_fixpoint::ThyFunc),
1225 Uif(FluxDefId),
1227 Def(FluxDefId),
1229 Cast,
1231}
1232
1233impl SpecFuncKind {
1234 pub fn def_id(&self) -> Option<FluxDefId> {
1235 match self {
1236 SpecFuncKind::Uif(flux_id) | SpecFuncKind::Def(flux_id) => Some(*flux_id),
1237 _ => None,
1238 }
1239 }
1240}
1241
1242impl<'fhir> Generics<'fhir> {
1243 pub fn get_param(&self, def_id: LocalDefId) -> &'fhir GenericParam<'fhir> {
1244 self.params
1245 .iter()
1246 .find(|p| p.def_id.local_id() == def_id)
1247 .unwrap()
1248 }
1249}
1250
1251impl<'fhir> RefinedBy<'fhir> {
1252 pub fn new(fields: FxIndexMap<Symbol, Sort<'fhir>>, sort_params: FxIndexSet<DefId>) -> Self {
1253 RefinedBy { sort_params, fields }
1254 }
1255
1256 pub fn trivial() -> Self {
1257 RefinedBy { sort_params: Default::default(), fields: Default::default() }
1258 }
1259}
1260
1261impl<'fhir> From<PolyFuncSort<'fhir>> for Sort<'fhir> {
1262 fn from(fsort: PolyFuncSort<'fhir>) -> Self {
1263 Self::Func(fsort)
1264 }
1265}
1266
1267impl FuncSort<'_> {
1268 pub fn inputs(&self) -> &[Sort<'_>] {
1269 &self.inputs_and_output[..self.inputs_and_output.len() - 1]
1270 }
1271
1272 pub fn output(&self) -> &Sort<'_> {
1273 &self.inputs_and_output[self.inputs_and_output.len() - 1]
1274 }
1275}
1276
1277impl rustc_errors::IntoDiagArg for Ty<'_> {
1278 fn into_diag_arg(self, _path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
1279 rustc_errors::DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
1280 }
1281}
1282
1283impl rustc_errors::IntoDiagArg for Path<'_> {
1284 fn into_diag_arg(self, _path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
1285 rustc_errors::DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
1286 }
1287}
1288
1289impl StructDef<'_> {
1290 pub fn is_opaque(&self) -> bool {
1291 matches!(self.kind, StructKind::Opaque)
1292 }
1293}
1294
1295impl fmt::Debug for FnSig<'_> {
1296 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1297 write!(f, "{:?}", self.decl)
1298 }
1299}
1300
1301impl fmt::Debug for FnDecl<'_> {
1302 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1303 if !self.requires.is_empty() {
1304 write!(f, "[{:?}] ", self.requires.iter().format(", "))?;
1305 }
1306 write!(f, "fn({:?}) -> {:?}", self.inputs.iter().format(", "), self.output)
1307 }
1308}
1309
1310impl fmt::Debug for FnOutput<'_> {
1311 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1312 if !self.params.is_empty() {
1313 write!(
1314 f,
1315 "exists<{}> ",
1316 self.params.iter().format_with(", ", |param, f| {
1317 f(&format_args!("{}: {:?}", param.name, param.sort))
1318 })
1319 )?;
1320 }
1321 write!(f, "{:?}", self.ret)?;
1322 if !self.ensures.is_empty() {
1323 write!(f, "; [{:?}]", self.ensures.iter().format(", "))?;
1324 }
1325
1326 Ok(())
1327 }
1328}
1329
1330impl fmt::Debug for Requires<'_> {
1331 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1332 if !self.params.is_empty() {
1333 write!(
1334 f,
1335 "forall {}.",
1336 self.params.iter().format_with(",", |param, f| {
1337 f(&format_args!("{}:{:?}", param.name, param.sort))
1338 })
1339 )?;
1340 }
1341 write!(f, "{:?}", self.pred)
1342 }
1343}
1344
1345impl fmt::Debug for Ensures<'_> {
1346 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1347 match self {
1348 Ensures::Type(loc, ty) => write!(f, "{loc:?}: {ty:?}"),
1349 Ensures::Pred(e) => write!(f, "{e:?}"),
1350 }
1351 }
1352}
1353
1354impl fmt::Debug for Ty<'_> {
1355 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1356 match &self.kind {
1357 TyKind::BaseTy(bty) => write!(f, "{bty:?}"),
1358 TyKind::Indexed(bty, idx) => write!(f, "{bty:?}[{idx:?}]"),
1359 TyKind::Exists(params, ty) => {
1360 write!(f, "{{")?;
1361 write!(
1362 f,
1363 "{}",
1364 params.iter().format_with(",", |param, f| {
1365 f(&format_args!("{}:{:?}", param.name, param.sort))
1366 })
1367 )?;
1368 if let TyKind::Constr(pred, ty) = &ty.kind {
1369 write!(f, ". {ty:?} | {pred:?}}}")
1370 } else {
1371 write!(f, ". {ty:?}}}")
1372 }
1373 }
1374 TyKind::StrgRef(_lft, loc, ty) => write!(f, "&strg <{loc:?}: {ty:?}>"),
1375 TyKind::Ref(_lft, mut_ty) => {
1376 write!(f, "&{}{:?}", mut_ty.mutbl.prefix_str(), mut_ty.ty)
1377 }
1378 TyKind::BareFn(bare_fn_ty) => {
1379 write!(f, "{bare_fn_ty:?}")
1380 }
1381 TyKind::Tuple(tys) => write!(f, "({:?})", tys.iter().format(", ")),
1382 TyKind::Array(ty, len) => write!(f, "[{ty:?}; {len:?}]"),
1383 TyKind::Never => write!(f, "!"),
1384 TyKind::Constr(pred, ty) => write!(f, "{{{ty:?} | {pred:?}}}"),
1385 TyKind::RawPtr(ty, Mutability::Not) => write!(f, "*const {ty:?}"),
1386 TyKind::RawPtr(ty, Mutability::Mut) => write!(f, "*mut {ty:?}"),
1387 TyKind::Infer => write!(f, "_"),
1388 TyKind::OpaqueDef(opaque_ty) => {
1389 write!(f, "impl trait <def_id = {:?}>", opaque_ty.def_id.resolved_id(),)
1390 }
1391 TyKind::TraitObject(poly_traits, _lft, _syntax) => {
1392 write!(f, "dyn {poly_traits:?}")
1393 }
1394 TyKind::Err(_) => write!(f, "err"),
1395 }
1396 }
1397}
1398
1399impl fmt::Debug for BareFnTy<'_> {
1400 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1401 if !self.generic_params.is_empty() {
1402 write!(
1403 f,
1404 "for<{}>",
1405 self.generic_params
1406 .iter()
1407 .map(|param| param.name.ident())
1408 .format(",")
1409 )?;
1410 }
1411 write!(f, "{:?}", self.decl)
1412 }
1413}
1414
1415impl fmt::Debug for Lifetime {
1416 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1417 match self {
1418 Lifetime::Hole(_) => write!(f, "'_"),
1419 Lifetime::Resolved(lft) => write!(f, "{lft:?}"),
1420 }
1421 }
1422}
1423
1424impl fmt::Debug for ConstArg {
1425 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1426 write!(f, "{:?}", self.kind)
1427 }
1428}
1429
1430impl fmt::Debug for ConstArgKind {
1431 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1432 match self {
1433 ConstArgKind::Lit(n) => write!(f, "{n}"),
1434 ConstArgKind::Param(p) => write!(f, "{p:?}"),
1435 ConstArgKind::Infer => write!(f, "_"),
1436 }
1437 }
1438}
1439
1440impl fmt::Debug for BaseTy<'_> {
1441 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1442 match &self.kind {
1443 BaseTyKind::Path(qpath) => write!(f, "{qpath:?}"),
1444 BaseTyKind::Slice(ty) => write!(f, "[{ty:?}]"),
1445 BaseTyKind::Err(_) => write!(f, "err"),
1446 }
1447 }
1448}
1449
1450impl fmt::Debug for QPath<'_> {
1451 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1452 match self {
1453 QPath::Resolved(_, path) => write!(f, "{path:?}"),
1454 QPath::TypeRelative(qself, assoc) => write!(f, "<{qself:?}>::{assoc:?}"),
1455 }
1456 }
1457}
1458
1459impl fmt::Debug for Path<'_> {
1460 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1461 write!(f, "{:?}", self.segments.iter().format("::"))?;
1462 if !self.refine.is_empty() {
1463 write!(f, "({:?})", self.refine.iter().format(", "))?;
1464 }
1465 Ok(())
1466 }
1467}
1468
1469impl fmt::Debug for PathSegment<'_> {
1470 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1471 write!(f, "{}", self.ident)?;
1472 let args: Vec<_> = self
1473 .args
1474 .iter()
1475 .map(|a| a as &dyn std::fmt::Debug)
1476 .chain(self.constraints.iter().map(|b| b as &dyn std::fmt::Debug))
1477 .collect();
1478 if !args.is_empty() {
1479 write!(f, "<{:?}>", args.iter().format(", "))?;
1480 }
1481 Ok(())
1482 }
1483}
1484
1485impl fmt::Debug for GenericArg<'_> {
1486 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1487 match self {
1488 GenericArg::Type(ty) => write!(f, "{ty:?}"),
1489 GenericArg::Lifetime(lft) => write!(f, "{lft:?}"),
1490 GenericArg::Const(cst) => write!(f, "{cst:?}"),
1491 GenericArg::Infer => write!(f, "_"),
1492 }
1493 }
1494}
1495
1496impl fmt::Debug for AssocItemConstraint<'_> {
1497 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1498 match &self.kind {
1499 AssocItemConstraintKind::Equality { term } => {
1500 write!(f, "{:?} = {:?}", self.ident, term)
1501 }
1502 }
1503 }
1504}
1505
1506impl fmt::Debug for AliasReft<'_> {
1507 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1508 write!(f, "<{:?} as {:?}>::{}", self.qself, self.path, self.name)
1509 }
1510}
1511
1512impl fmt::Debug for QuantKind {
1513 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1514 match self {
1515 QuantKind::Forall => write!(f, "∀"),
1516 QuantKind::Exists => write!(f, "∃"),
1517 }
1518 }
1519}
1520
1521impl fmt::Debug for Expr<'_> {
1522 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1523 match self.kind {
1524 ExprKind::Var(x, ..) => write!(f, "{x:?}"),
1525 ExprKind::BinaryOp(op, e1, e2) => write!(f, "({e1:?} {op:?} {e2:?})"),
1526 ExprKind::PrimApp(op, e1, e2) => write!(f, "[{op:?}]({e1:?}, {e2:?})"),
1527 ExprKind::UnaryOp(op, e) => write!(f, "{op:?}{e:?}"),
1528 ExprKind::Literal(lit) => write!(f, "{lit:?}"),
1529 ExprKind::App(uf, es) => write!(f, "{uf:?}({:?})", es.iter().format(", ")),
1530 ExprKind::Alias(alias, refine_args) => {
1531 write!(f, "{alias:?}({:?})", refine_args.iter().format(", "))
1532 }
1533 ExprKind::IfThenElse(p, e1, e2) => {
1534 write!(f, "(if {p:?} {{ {e1:?} }} else {{ {e2:?} }})")
1535 }
1536 ExprKind::Dot(var, fld) => write!(f, "{var:?}.{fld}"),
1537 ExprKind::Abs(params, body) => {
1538 write!(
1539 f,
1540 "|{}| {body:?}",
1541 params.iter().format_with(", ", |param, f| {
1542 f(&format_args!("{}: {:?}", param.name, param.sort))
1543 })
1544 )
1545 }
1546 ExprKind::Record(flds) => {
1547 write!(f, "{{ {:?} }}", flds.iter().format(", "))
1548 }
1549 ExprKind::Constructor(path, exprs, spread) => {
1550 if let Some(path) = path
1551 && let Some(s) = spread
1552 {
1553 write!(f, "{:?} {{ {:?}, ..{:?} }}", path, exprs.iter().format(", "), s)
1554 } else if let Some(path) = path {
1555 write!(f, "{:?} {{ {:?} }}", path, exprs.iter().format(", "))
1556 } else if let Some(s) = spread {
1557 write!(f, "{{ {:?} ..{:?} }}", exprs.iter().format(", "), s)
1558 } else {
1559 write!(f, "{{ {:?} }}", exprs.iter().format(", "))
1560 }
1561 }
1562 ExprKind::BoundedQuant(kind, refine_param, rng, expr) => {
1563 write!(f, "{kind:?} {refine_param:?} in {}.. {} {{ {expr:?} }}", rng.start, rng.end)
1564 }
1565 ExprKind::Err(_) => write!(f, "err"),
1566 ExprKind::Block(decls, body) => {
1567 for decl in decls {
1568 write!(f, "let {:?} = {:?};", decl.param, decl.init)?;
1569 }
1570 write!(f, "{body:?}")
1571 }
1572 }
1573 }
1574}
1575
1576impl fmt::Debug for PathExpr<'_> {
1577 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1578 write!(f, "{}", self.segments.iter().format("::"))
1579 }
1580}
1581
1582impl fmt::Debug for Lit {
1583 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1584 match self {
1585 Lit::Int(i, Some(NumLitKind::Real)) => write!(f, "{i}real"),
1586 Lit::Int(i, _) => write!(f, "{i}"),
1587 Lit::Bool(b) => write!(f, "{b}"),
1588 Lit::Str(s) => write!(f, "\"{s:?}\""),
1589 Lit::Char(c) => write!(f, "\'{c}\'"),
1590 }
1591 }
1592}
1593
1594impl fmt::Debug for Sort<'_> {
1595 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1596 match self {
1597 Sort::Path(path) => write!(f, "{path:?}"),
1598 Sort::BitVec(w) => write!(f, "bitvec({w})"),
1599 Sort::Loc => write!(f, "loc"),
1600 Sort::Func(fsort) => write!(f, "{fsort:?}"),
1601 Sort::SortOf(bty) => write!(f, "<{bty:?}>::sort"),
1602 Sort::Infer => write!(f, "_"),
1603 Sort::Err(_) => write!(f, "err"),
1604 }
1605 }
1606}
1607
1608impl fmt::Debug for SortPath<'_> {
1609 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1610 write!(f, "{:?}", self.res)?;
1611 if !self.args.is_empty() {
1612 write!(f, "<{:?}>", self.args.iter().format(", "))?;
1613 }
1614 Ok(())
1615 }
1616}
1617
1618impl fmt::Debug for SortRes {
1619 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1620 match self {
1621 SortRes::PrimSort(PrimSort::Bool) => write!(f, "bool"),
1622 SortRes::PrimSort(PrimSort::Int) => write!(f, "int"),
1623 SortRes::PrimSort(PrimSort::Real) => write!(f, "real"),
1624 SortRes::PrimSort(PrimSort::Char) => write!(f, "char"),
1625 SortRes::PrimSort(PrimSort::Str) => write!(f, "str"),
1626 SortRes::PrimSort(PrimSort::Set) => write!(f, "Set"),
1627 SortRes::PrimSort(PrimSort::Map) => write!(f, "Map"),
1628 SortRes::SortParam(n) => write!(f, "@{n}"),
1629 SortRes::TyParam(def_id) => write!(f, "{}::sort", def_id_to_string(*def_id)),
1630 SortRes::SelfParam { trait_id } => {
1631 write!(f, "{}::Self::sort", def_id_to_string(*trait_id))
1632 }
1633 SortRes::SelfAlias { alias_to } => {
1634 write!(f, "{}::Self::sort", def_id_to_string(*alias_to))
1635 }
1636 SortRes::SelfParamAssoc { ident: assoc, .. } => {
1637 write!(f, "Self::{assoc}")
1638 }
1639 SortRes::User { name } => write!(f, "{name}"),
1640 SortRes::Adt(def_id) => write!(f, "{}::sort", def_id_to_string(*def_id)),
1641 }
1642 }
1643}
1644
1645impl fmt::Debug for PolyFuncSort<'_> {
1646 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1647 if self.params > 0 {
1648 write!(f, "for<{}>{:?}", self.params, self.fsort)
1649 } else {
1650 write!(f, "{:?}", self.fsort)
1651 }
1652 }
1653}
1654
1655impl fmt::Debug for FuncSort<'_> {
1656 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1657 match self.inputs() {
1658 [input] => {
1659 write!(f, "{:?} -> {:?}", input, self.output())
1660 }
1661 inputs => {
1662 write!(f, "({:?}) -> {:?}", inputs.iter().format(", "), self.output())
1663 }
1664 }
1665 }
1666}