1pub mod visit;
2
3use std::{fmt, ops::Range};
4
5pub use rustc_ast::{
6 Mutability,
7 token::{Lit, LitKind},
8};
9pub use rustc_span::{Span, symbol::Ident};
10use rustc_span::{Symbol, symbol::sym};
11
12use crate::surface::visit::Visitor;
13
14#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
17pub struct NodeId(pub(super) usize);
18
19impl NodeId {
20 pub fn as_usize(&self) -> usize {
21 self.0
22 }
23}
24
25#[derive(Debug)]
26pub struct SortDecl {
27 pub name: Ident,
28}
29
30#[derive(Debug)]
31pub enum Item {
32 Qualifier(Qualifier),
33 FuncDef(SpecFunc),
34 SortDecl(SortDecl),
35}
36
37impl Item {
38 pub fn name(&self) -> Ident {
39 match self {
40 Item::Qualifier(qualifier) => qualifier.name,
41 Item::FuncDef(spec_func) => spec_func.name,
42 Item::SortDecl(sort_decl) => sort_decl.name,
43 }
44 }
45}
46
47#[derive(Debug)]
48pub struct Qualifier {
49 pub name: Ident,
50 pub params: RefineParams,
51 pub expr: Expr,
52 pub span: Span,
53 pub global: bool,
54}
55
56#[derive(Debug)]
59pub struct SpecFunc {
60 pub name: Ident,
61 pub sort_vars: Vec<Ident>,
62 pub params: RefineParams,
63 pub output: Sort,
64 pub body: Option<Expr>,
66 pub hide: bool,
70}
71
72#[derive(Debug)]
73pub struct Generics {
74 pub params: Vec<GenericParam>,
75 pub predicates: Option<Vec<WhereBoundPredicate>>,
76 pub span: Span,
77}
78
79#[derive(Debug)]
80pub struct GenericParam {
81 pub name: Ident,
82 pub kind: GenericParamKind,
83 pub node_id: NodeId,
84}
85
86#[derive(Debug)]
87pub enum GenericParamKind {
88 Type,
89 Base,
90}
91
92#[derive(Debug)]
93pub struct TyAlias {
94 pub ident: Ident,
95 pub generics: Generics,
96 pub params: RefineParams,
97 pub index: Option<RefineParam>,
98 pub ty: Ty,
99 pub node_id: NodeId,
100 pub span: Span,
101}
102
103#[derive(Debug)]
104pub struct ConstantInfo {
105 pub expr: Option<Expr>,
106}
107
108#[derive(Debug)]
109pub struct StructDef {
110 pub generics: Option<Generics>,
111 pub refined_by: Option<RefineParams>,
112 pub fields: Vec<Option<Ty>>,
113 pub opaque: bool,
114 pub invariants: Vec<Expr>,
115 pub node_id: NodeId,
116}
117
118impl StructDef {
119 pub fn needs_resolving(&self) -> bool {
121 self.fields.iter().any(Option::is_some)
122 }
123}
124
125#[derive(Debug)]
126pub struct EnumDef {
127 pub generics: Option<Generics>,
128 pub refined_by: Option<RefineParams>,
129 pub variants: Vec<Option<VariantDef>>,
130 pub invariants: Vec<Expr>,
131 pub node_id: NodeId,
132 pub reflected: bool,
133}
134
135impl EnumDef {
136 pub fn needs_resolving(&self) -> bool {
138 self.variants.iter().any(Option::is_some)
139 }
140}
141
142#[derive(Debug)]
143pub struct VariantDef {
144 pub fields: Vec<Ty>,
145 pub ret: Option<VariantRet>,
146 pub node_id: NodeId,
147 pub span: Span,
148}
149
150#[derive(Debug)]
151pub struct VariantRet {
152 pub path: Path,
153 pub indices: Indices,
156}
157
158pub type RefineParams = Vec<RefineParam>;
159
160#[derive(Debug, Default)]
161pub struct QualNames {
162 pub names: Vec<Ident>,
163}
164
165#[derive(Debug, Default)]
166pub struct RevealNames {
167 pub names: Vec<Ident>,
168}
169
170#[derive(Debug)]
171pub struct RefineParam {
172 pub ident: Ident,
173 pub sort: Sort,
174 pub mode: Option<ParamMode>,
175 pub span: Span,
176 pub node_id: NodeId,
177}
178
179#[derive(Clone, Copy, Debug, PartialEq, Eq)]
180pub enum ParamMode {
181 Horn,
182 Hindley,
183}
184
185#[derive(Debug)]
186pub enum Sort {
187 Base(BaseSort),
189 Func { inputs: Vec<BaseSort>, output: BaseSort },
192 Infer,
194}
195
196#[derive(Debug)]
197pub enum BaseSort {
198 BitVec(u32),
200 SortOf(Box<Ty>, Path),
201 Path(SortPath),
202}
203
204#[derive(Debug)]
206pub struct SortPath {
207 pub segments: Vec<Ident>,
209 pub args: Vec<BaseSort>,
211 pub node_id: NodeId,
212}
213
214#[derive(Debug)]
215pub struct Impl {
216 pub generics: Option<Generics>,
217 pub assoc_refinements: Vec<ImplAssocReft>,
218}
219
220#[derive(Debug)]
221pub struct ImplAssocReft {
222 pub name: Ident,
223 pub params: RefineParams,
224 pub output: BaseSort,
225 pub body: Expr,
226 pub span: Span,
227}
228
229pub struct Trait {
230 pub generics: Option<Generics>,
231 pub assoc_refinements: Vec<TraitAssocReft>,
232}
233
234#[derive(Debug)]
235pub struct TraitAssocReft {
236 pub name: Ident,
237 pub params: RefineParams,
238 pub output: BaseSort,
239 pub body: Option<Expr>,
240 pub span: Span,
241}
242
243#[derive(Debug)]
244pub struct FnSpec {
245 pub fn_sig: Option<FnSig>,
246 pub qual_names: Option<QualNames>,
247 pub reveal_names: Option<RevealNames>,
248}
249
250#[derive(Debug)]
251pub struct FnSig {
252 pub asyncness: Async,
253 pub ident: Option<Ident>,
254 pub generics: Generics,
255 pub params: RefineParams,
256 pub requires: Vec<Requires>,
258 pub inputs: Vec<FnInput>,
260 pub output: FnOutput,
261 pub span: Span,
263 pub node_id: NodeId,
264}
265
266#[derive(Debug)]
267pub struct Requires {
268 pub params: RefineParams,
270 pub pred: Expr,
271}
272
273#[derive(Debug)]
274pub struct FnOutput {
275 pub returns: FnRetTy,
277 pub ensures: Vec<Ensures>,
279 pub node_id: NodeId,
280}
281
282#[derive(Debug)]
283pub enum Ensures {
284 Type(Ident, Ty, NodeId),
286 Pred(Expr),
288}
289
290#[derive(Debug)]
291pub enum FnRetTy {
292 Default(Span),
293 Ty(Ty),
294}
295
296#[derive(Debug, Copy, Clone)]
297pub enum Async {
298 Yes { node_id: NodeId, span: Span },
299 No,
300}
301
302#[derive(Debug)]
303pub struct WhereBoundPredicate {
304 pub span: Span,
305 pub bounded_ty: Ty,
306 pub bounds: GenericBounds,
307}
308
309pub type GenericBounds = Vec<TraitRef>;
310
311#[derive(Debug)]
312pub struct TraitRef {
313 pub path: Path,
314 pub node_id: NodeId,
315}
316
317impl TraitRef {
318 fn is_fn_trait_name(name: Symbol) -> bool {
319 name == sym::FnOnce || name == sym::FnMut || name == sym::Fn
320 }
321
322 pub fn as_fn_trait_ref(&self) -> Option<(&GenericArg, &GenericArg)> {
323 if let [segment] = self.path.segments.as_slice()
324 && Self::is_fn_trait_name(segment.ident.name)
325 && let [in_arg, out_arg] = segment.args.as_slice()
326 {
327 return Some((in_arg, out_arg));
328 }
329 None
330 }
331}
332
333#[derive(Debug)]
334pub enum FnInput {
335 Constr(Ident, Path, Expr, NodeId),
337 StrgRef(Ident, Ty, NodeId),
339 Ty(Option<Ident>, Ty, NodeId),
342}
343
344#[derive(Debug)]
345pub struct Ty {
346 pub kind: TyKind,
347 pub node_id: NodeId,
348 pub span: Span,
349}
350
351#[derive(Debug)]
352pub enum TyKind {
353 Base(BaseTy),
355 Indexed {
357 bty: BaseTy,
358 indices: Indices,
359 },
360 Exists {
362 bind: Ident,
363 bty: BaseTy,
364 pred: Expr,
365 },
366 GeneralExists {
367 params: RefineParams,
368 ty: Box<Ty>,
369 pred: Option<Expr>,
370 },
371 Ref(Mutability, Box<Ty>),
373 Constr(Expr, Box<Ty>),
375 Tuple(Vec<Ty>),
376 Array(Box<Ty>, ConstArg),
377 ImplTrait(NodeId, GenericBounds),
379 Hole,
380}
381
382impl Ty {
383 pub fn is_refined(&self) -> bool {
384 struct IsRefinedVisitor {
385 is_refined: bool,
386 }
387 let mut vis = IsRefinedVisitor { is_refined: false };
388 impl visit::Visitor for IsRefinedVisitor {
389 fn visit_ty(&mut self, ty: &Ty) {
390 match &ty.kind {
391 TyKind::Tuple(_)
392 | TyKind::Ref(..)
393 | TyKind::Array(..)
394 | TyKind::ImplTrait(..)
395 | TyKind::Hole
396 | TyKind::Base(_) => {
397 visit::walk_ty(self, ty);
398 }
399 TyKind::Indexed { .. }
400 | TyKind::Exists { .. }
401 | TyKind::GeneralExists { .. }
402 | TyKind::Constr(..) => {
403 self.is_refined = true;
404 }
405 }
406 }
407 }
408 vis.visit_ty(self);
409 vis.is_refined
410 }
411}
412#[derive(Debug)]
413pub struct BaseTy {
414 pub kind: BaseTyKind,
415 pub span: Span,
416}
417
418#[derive(Debug)]
419pub enum BaseTyKind {
420 Path(Option<Box<Ty>>, Path),
421 Slice(Box<Ty>),
422}
423
424#[derive(PartialEq, Eq, Clone, Debug, Copy)]
425pub struct ConstArg {
426 pub kind: ConstArgKind,
427 pub span: Span,
428}
429
430#[derive(PartialEq, Eq, Clone, Debug, Copy)]
431pub enum ConstArgKind {
432 Lit(usize),
433 Infer,
434}
435
436#[derive(Debug)]
437pub struct Indices {
438 pub indices: Vec<RefineArg>,
439 pub span: Span,
440}
441
442#[derive(Debug)]
443pub enum RefineArg {
444 Bind(Ident, BindKind, Span, NodeId),
446 Expr(Expr),
447 Abs(RefineParams, Expr, Span, NodeId),
448}
449
450#[derive(Debug, Clone, Copy)]
451pub enum BindKind {
452 At,
453 Pound,
454}
455
456#[derive(Debug)]
457pub struct Path {
458 pub segments: Vec<PathSegment>,
459 pub refine: Vec<RefineArg>,
460 pub node_id: NodeId,
461 pub span: Span,
462}
463
464impl Path {
465 pub fn last(&self) -> &PathSegment {
466 self.segments
467 .last()
468 .expect("path must have at least one segment")
469 }
470}
471
472#[derive(Debug)]
473pub struct PathSegment {
474 pub ident: Ident,
475 pub args: Vec<GenericArg>,
476 pub node_id: NodeId,
477}
478
479#[derive(Debug)]
480pub struct GenericArg {
481 pub kind: GenericArgKind,
482 pub node_id: NodeId,
483}
484
485#[derive(Debug)]
486pub enum GenericArgKind {
487 Type(Ty),
488 Constraint(Ident, Ty),
489}
490
491#[derive(Debug)]
492pub struct FieldExpr {
493 pub ident: Ident,
494 pub expr: Expr,
495 pub span: Span,
496 pub node_id: NodeId,
497}
498
499#[derive(Debug)]
500pub struct Spread {
501 pub expr: Expr,
502 pub span: Span,
503 pub node_id: NodeId,
504}
505
506#[derive(Debug)]
507pub enum ConstructorArg {
508 FieldExpr(FieldExpr),
509 Spread(Spread),
510}
511
512#[derive(Debug)]
513pub struct Expr {
514 pub kind: ExprKind,
515 pub node_id: NodeId,
516 pub span: Span,
517}
518
519#[derive(Debug)]
520pub enum QuantKind {
521 Forall,
522 Exists,
523}
524
525#[derive(Debug)]
526pub enum ExprKind {
527 Path(ExprPath),
528 Dot(Box<Expr>, Ident),
529 Literal(Lit),
530 BinaryOp(BinOp, Box<[Expr; 2]>),
531 UnaryOp(UnOp, Box<Expr>),
532 Call(Box<Expr>, Vec<Expr>),
533 AssocReft(Box<Ty>, Path, Ident),
535 IfThenElse(Box<[Expr; 3]>),
536 Constructor(Option<ExprPath>, Vec<ConstructorArg>),
537 BoundedQuant(QuantKind, RefineParam, Range<usize>, Box<Expr>),
538 Block(Vec<LetDecl>, Box<Expr>),
539}
540
541#[derive(Debug)]
542pub struct LetDecl {
543 pub param: RefineParam,
544 pub init: Expr,
545}
546
547#[derive(Debug, Clone)]
549pub struct ExprPath {
550 pub segments: Vec<ExprPathSegment>,
551 pub node_id: NodeId,
552 pub span: Span,
553}
554
555#[derive(Debug, Clone)]
556pub struct ExprPathSegment {
557 pub ident: Ident,
558 pub node_id: NodeId,
559}
560
561#[derive(Copy, Clone, PartialEq)]
562pub enum BinOp {
563 Iff,
564 Imp,
565 Or,
566 And,
567 Eq,
568 Ne,
569 Gt,
570 Ge,
571 Lt,
572 Le,
573 Add,
574 Sub,
575 Mul,
576 Div,
577 Mod,
578 BitAnd,
579 BitOr,
580 BitShl,
581 BitShr,
582}
583
584impl fmt::Debug for BinOp {
585 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
586 match self {
587 BinOp::Iff => write!(f, "<=>"),
588 BinOp::Imp => write!(f, "=>"),
589 BinOp::Or => write!(f, "||"),
590 BinOp::And => write!(f, "&&"),
591 BinOp::Eq => write!(f, "=="),
592 BinOp::Ne => write!(f, "!="),
593 BinOp::Lt => write!(f, "<"),
594 BinOp::Le => write!(f, "<="),
595 BinOp::Gt => write!(f, ">"),
596 BinOp::Ge => write!(f, ">="),
597 BinOp::Add => write!(f, "+"),
598 BinOp::Sub => write!(f, "-"),
599 BinOp::Mod => write!(f, "mod"),
600 BinOp::Mul => write!(f, "*"),
601 BinOp::Div => write!(f, "/"),
602 BinOp::BitAnd => write!(f, "&"),
603 BinOp::BitOr => write!(f, "|"),
604 BinOp::BitShl => write!(f, "<<"),
605 BinOp::BitShr => write!(f, ">>"),
606 }
607 }
608}
609
610#[derive(Copy, Clone)]
611pub enum UnOp {
612 Not,
613 Neg,
614}
615
616impl fmt::Debug for UnOp {
617 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
618 match self {
619 Self::Not => write!(f, "!"),
620 Self::Neg => write!(f, "-"),
621 }
622 }
623}
624
625impl BindKind {
626 pub fn token_str(&self) -> &'static str {
627 match self {
628 BindKind::At => "@",
629 BindKind::Pound => "#",
630 }
631 }
632}
633
634pub struct Punctuated<T, P> {
636 inner: Vec<(T, P)>,
637 last: Option<Box<T>>,
638}
639
640impl<T, P> From<Vec<(T, P)>> for Punctuated<T, P> {
641 fn from(inner: Vec<(T, P)>) -> Self {
642 Self { inner, last: None }
643 }
644}
645
646impl<T, P> Punctuated<T, P> {
647 pub fn len(&self) -> usize {
648 self.inner.len() + self.last.is_some() as usize
649 }
650
651 pub fn is_empty(&self) -> bool {
654 self.inner.len() == 0 && self.last.is_none()
655 }
656
657 pub fn push_value(&mut self, value: T) {
665 assert!(
666 self.empty_or_trailing(),
667 "Punctuated::push_value: cannot push value if Punctuated is missing trailing punctuation",
668 );
669
670 self.last = Some(Box::new(value));
671 }
672
673 pub fn empty_or_trailing(&self) -> bool {
678 self.last.is_none()
679 }
680
681 pub fn trailing_punct(&self) -> bool {
684 self.last.is_none() && !self.is_empty()
685 }
686
687 pub fn into_values(self) -> Vec<T> {
688 let mut v: Vec<T> = self.inner.into_iter().map(|(v, _)| v).collect();
689 if let Some(last) = self.last {
690 v.push(*last);
691 }
692 v
693 }
694}