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