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