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