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