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