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