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