Skip to content

Commit e47b293

Browse files
committed
Add documentation to src/rty.rs and src/rty/*.rs
1 parent f0ddfed commit e47b293

5 files changed

Lines changed: 144 additions & 0 deletions

File tree

src/rty.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,42 @@
1+
//! Data structures for refinement types.
2+
//!
3+
//! Thrust is a refinement type system, and so its analysis is about giving refinement types to
4+
//! variables and terms. This module defines the data structures for representing refinement
5+
//! types. The central data structure is [`RefinedType`], which is just [`Type`] plus [`Refinement`].
6+
//!
7+
//! Note that there are two notions of "variables" in this module. First is a type variable which is
8+
//! a polymorphic type parameter which is represented by [`TypeParamIdx`], and forms one of valid type as [`ParamType`].
9+
//! `T` in `struct S<T> { f: T }` is a type variable. See [`params`] module for the handling of type parameters.
10+
//! Second is a logical variable which is a variable that can appear in logical predicates.
11+
//! `x` and `y` in `{ x: int | x > y }` are logical variables.
12+
//! The actual representation of logical variables varies by context and so it is often parameterized
13+
//! as a type parameter in this module (`T` in `Type<T>`). In [`FunctionType`], logical variables are
14+
//! function parameters (`Type<FunctionParamIdx`), and during the actual analysis, logical variables are
15+
//! program variables bound in the environment (`Type<Var>`, see [`crate::refine::Var`]).
16+
//! We have [`RefinedTypeVar<T>`] to denote logical variables in refinement predicates, which
17+
//! accepts existential variables and a variable bound in the refinement type (`x` in `{ x: T | phi
18+
//! }`) in addition to variables `T` from the outer scope. This module also contains [`Closed`] which is
19+
//! used to denote a closed type, so `Type<Closed>` ensures no logical variables from the outer scope
20+
//! appear in that type.
21+
//!
22+
//! We have distinct types for each variant of [`Type`], such as [`FunctionType`] and
23+
//! [`PointerType`]. [`Type`], [`RefinedType`] and these variant types share some common operations:
24+
//!
25+
//! - `subst_var`: Substitutes logical variables with logical terms.
26+
//! - `map_var`: Maps logical variables to other logical variables.
27+
//! - `free_ty_params`: Collects free type parameters [`TypeParamIdx`] in the type.
28+
//! - `subst_ty_params`: Substitutes type parameters with other types. Since this replaces
29+
//! type parameters with refinement types, [`Type`] does not implement this, and
30+
//! [`RefinedType::subst_ty_params`] handles the substitution logic instead.
31+
//! - `strip_refinement`: Strips the refinements recursively and returns a [`Closed`] type.
32+
//!
33+
//! This module also implements several logics for manipulating refinement types and is extensively used in
34+
//! upstream logic in the [`crate::refine`] and [`crate::analyze`] modules.
35+
//!
36+
//! - [`template`]: Generates "template" refinement types with unknown predicates to be inferred.
37+
//! - [`subtyping`]: Generates CHC constraints [`crate::chc`] from subtyping relations between types.
38+
//! - [`clause_builder`]: Helper to build [`crate::chc::Clause`] from the refinement types.
39+
140
use std::collections::{HashMap, HashSet};
241

342
use pretty::{termcolor, Pretty};
@@ -19,6 +58,11 @@ mod params;
1958
pub use params::{TypeParamIdx, TypeParamSubst, TypeParams};
2059

2160
rustc_index::newtype_index! {
61+
/// An index representing function parameter.
62+
///
63+
/// We manage function parameters using indices that are unique in a function.
64+
/// [`FunctionType`] contains `IndexVec<FunctionParamIdx, RefinedType<FunctionParamIdx>>`
65+
/// that manages the indices and types of the function parameters.
2266
#[orderable]
2367
#[debug_format = "${}"]
2468
pub struct FunctionParamIdx { }
@@ -39,6 +83,11 @@ where
3983
}
4084
}
4185

86+
/// A function type.
87+
///
88+
/// In Thrust, function types are closed. Because of that, function types, thus its parameters and
89+
/// return type only refer to the parameters of the function itself using [`FunctionParamIdx`] and
90+
/// do not accept other type of variables from the environment.
4291
#[derive(Debug, Clone)]
4392
pub struct FunctionType {
4493
pub params: IndexVec<FunctionParamIdx, RefinedType<FunctionParamIdx>>,
@@ -74,6 +123,8 @@ impl FunctionType {
74123
}
75124
}
76125

126+
/// Because function types are always closed in Thrust, we can convert this into
127+
/// [`Type<Closed>`].
77128
pub fn into_closed_ty(self) -> Type<Closed> {
78129
Type::Function(self)
79130
}
@@ -104,6 +155,7 @@ impl FunctionType {
104155
}
105156
}
106157

158+
/// The kind of a reference, which is either mutable or immutable.
107159
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
108160
pub enum RefKind {
109161
Mut,
@@ -128,6 +180,7 @@ where
128180
}
129181
}
130182

183+
/// The kind of a pointer, which is either a reference or an owned pointer.
131184
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
132185
pub enum PointerKind {
133186
Ref(RefKind),
@@ -167,6 +220,7 @@ impl PointerKind {
167220
}
168221
}
169222

223+
/// A pointer type.
170224
#[derive(Debug, Clone)]
171225
pub struct PointerType<T> {
172226
pub kind: PointerKind,
@@ -275,6 +329,11 @@ impl<T> PointerType<T> {
275329
}
276330
}
277331

332+
/// A tuple type.
333+
///
334+
/// Note that the current implementation uses tuples to represent structs. See
335+
/// implementation in `crate::refine::template` module for details.
336+
/// It is our TODO to improve the struct representation.
278337
#[derive(Debug, Clone)]
279338
pub struct TupleType<T> {
280339
pub elems: Vec<RefinedType<T>>,
@@ -374,13 +433,15 @@ impl<T> TupleType<T> {
374433
}
375434
}
376435

436+
/// A definition of an enum variant, found in [`EnumDatatypeDef`].
377437
#[derive(Debug, Clone)]
378438
pub struct EnumVariantDef {
379439
pub name: chc::DatatypeSymbol,
380440
pub discr: u32,
381441
pub field_tys: Vec<Type<Closed>>,
382442
}
383443

444+
/// A definition of an enum datatype.
384445
#[derive(Debug, Clone)]
385446
pub struct EnumDatatypeDef {
386447
pub name: chc::DatatypeSymbol,
@@ -394,6 +455,9 @@ impl EnumDatatypeDef {
394455
}
395456
}
396457

458+
/// An enum type.
459+
///
460+
/// An enum type includes its type arguments and the argument types can refer to outer variables `T`.
397461
#[derive(Debug, Clone)]
398462
pub struct EnumType<T> {
399463
pub symbol: chc::DatatypeSymbol,
@@ -495,6 +559,7 @@ impl<T> EnumType<T> {
495559
}
496560
}
497561

562+
/// A type parameter.
498563
#[derive(Debug, Clone)]
499564
pub struct ParamType {
500565
pub idx: TypeParamIdx,
@@ -523,6 +588,7 @@ impl ParamType {
523588
}
524589
}
525590

591+
/// An underlying type of a refinement type.
526592
#[derive(Debug, Clone)]
527593
pub enum Type<T> {
528594
Int,
@@ -803,6 +869,10 @@ impl Type<Closed> {
803869
}
804870
}
805871

872+
/// A marker type for closed types.
873+
///
874+
/// Because the value of `Closed` can never exist, `Type<Closed>` ensures that no
875+
/// logical variables from outer scope appear in the type.
806876
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
807877
pub enum Closed {}
808878

@@ -822,6 +892,11 @@ where
822892
}
823893

824894
rustc_index::newtype_index! {
895+
/// An index representing existential variables.
896+
///
897+
/// We manage existential variables using indices that are unique in a [`Formula`].
898+
/// [`Formula`] contains `IndexVec<ExistentialVarIdx, chc::Sort>` that manages the indices
899+
/// and sorts of the existential variables.
825900
#[orderable]
826901
#[debug_format = "e{}"]
827902
pub struct ExistentialVarIdx { }
@@ -846,6 +921,15 @@ pub trait ShiftExistential {
846921
fn shift_existential(self, offset: usize) -> Self;
847922
}
848923

924+
/// A logical variable in a refinement predicate.
925+
///
926+
/// Given a refinement type `{ v: T | ∃e. φ }`, there are three cases of logical variables
927+
/// occurring in the predicate `φ`:
928+
///
929+
/// - `RefinedTypeVar::Value`: a variable `v` representing the value of the type
930+
/// - `RefinedTypeVar::Existential`: an existential variable `e`
931+
/// - `RefinedTypeVar::Free`: a variable from the outer scope, such as function parameters or
932+
/// variables bound in the environment
849933
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
850934
pub enum RefinedTypeVar<FV> {
851935
Value,
@@ -908,6 +992,9 @@ impl<T> ShiftExistential for RefinedTypeVar<T> {
908992
}
909993
}
910994

995+
/// A formula, potentially equipped with an existential quantifier.
996+
///
997+
/// Note: This is not to be confused with [`crate::chc::Formula`] in the [`crate::chc`] module, which is a different notion.
911998
#[derive(Debug, Clone)]
912999
pub struct Formula<V> {
9131000
pub existentials: IndexVec<ExistentialVarIdx, chc::Sort>,
@@ -1051,6 +1138,10 @@ where
10511138
}
10521139
}
10531140

1141+
/// A refinement predicate in a refinement type.
1142+
///
1143+
/// This is a [`Formula`], but gives an explicit representation of the kinds of variables that appear in
1144+
/// the refinement predicates. See [`RefinedTypeVar`] for details.
10541145
pub type Refinement<FV = Closed> = Formula<RefinedTypeVar<FV>>;
10551146

10561147
impl<FV> Refinement<FV> {
@@ -1105,6 +1196,10 @@ impl<FV> Refinement<FV> {
11051196
}
11061197
}
11071198

1199+
/// A helper type to map logical variables in a refinement at once.
1200+
///
1201+
/// This is essentially just calling `Refinement::map_var`, but provides a convenient interface to
1202+
/// construct the mapping of the variables.
11081203
#[derive(Debug, Clone)]
11091204
pub struct Instantiator<T> {
11101205
value_var: Option<T>,
@@ -1140,6 +1235,7 @@ impl<T> Instantiator<T> {
11401235
}
11411236
}
11421237

1238+
/// A refinement type.
11431239
#[derive(Debug, Clone)]
11441240
pub struct RefinedType<FV = Closed> {
11451241
pub ty: Type<FV>,

src/rty/clause_builder.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
1+
//! Helpers to build [`crate::chc::Clause`] from the refinement types.
2+
//!
3+
//! This module provides an extension trait named [`ClauseBuilderExt`] for [`chc::ClauseBuilder`]
4+
//! that allows it to work with refinement types. It provides a convenient way to generate CHC clauses from
5+
//! [`Refinement`]s, by handling the mapping of [`RefinedTypeVar`] to [`chc::TermVarIdx`].
6+
//! This is primarily used to generate clauses from [`super::subtyping`] constraints between refinement types.
7+
18
use crate::chc;
29

310
use super::{Refinement, Type};
411

12+
/// An extension trait for [`chc::ClauseBuilder`] to work with refinement types.
13+
///
14+
/// We implement a custom logic to deal with [`Refinement`]s in [`RefinementClauseBuilder`],
15+
/// and this extension trait provides methods to create [`RefinementClauseBuilder`]s while
16+
/// specifying how to handle [`RefinedTypeVar::Value`] during the instantiation.
517
pub trait ClauseBuilderExt {
618
fn with_value_var<'a, T>(&'a mut self, ty: &Type<T>) -> RefinementClauseBuilder<'a>;
719
fn with_mapped_value_var<T>(&mut self, v: T) -> RefinementClauseBuilder<'_>
@@ -31,6 +43,10 @@ impl ClauseBuilderExt for chc::ClauseBuilder {
3143
}
3244
}
3345

46+
/// A builder for a CHC clause with a refinement.
47+
///
48+
/// You can supply [`Refinement`]s as the body and head of the clause directly, and this builder
49+
/// will take care of mapping the variables appropriately.
3450
pub struct RefinementClauseBuilder<'a> {
3551
builder: &'a mut chc::ClauseBuilder,
3652
value_var: Option<chc::TermVarIdx>,

src/rty/params.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Data structures for type parameters and substitutions.
2+
13
use std::collections::BTreeMap;
24

35
use pretty::{termcolor, Pretty};
@@ -8,6 +10,7 @@ use crate::chc;
810
use super::{Closed, RefinedType};
911

1012
rustc_index::newtype_index! {
13+
/// An index representing a type parameter.
1114
#[orderable]
1215
#[debug_format = "T{}"]
1316
pub struct TypeParamIdx { }
@@ -38,6 +41,7 @@ impl TypeParamIdx {
3841

3942
pub type TypeParams<T> = IndexVec<TypeParamIdx, RefinedType<T>>;
4043

44+
/// A substitution for type parameters that maps type parameters to refinement types.
4145
#[derive(Debug, Clone)]
4246
pub struct TypeParamSubst<T> {
4347
subst: BTreeMap<TypeParamIdx, RefinedType<T>>,

src/rty/subtyping.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1+
//! Translation of subtyping relations into CHC constraints.
2+
13
use crate::chc;
24
use crate::pretty::PrettyDisplayExt;
35

46
use super::{ClauseBuilderExt as _, Closed, PointerKind, RefKind, RefinedType, Type};
57

8+
/// A scope for building clauses.
9+
///
10+
/// The construction of CHC clauses requires knowledge of the current
11+
/// environment to determine variable sorts and include necessary premises.
12+
/// This trait abstracts the preparation of a [`chc::ClauseBuilder`] to allow an
13+
/// environment defined outside of this module (in Thrust, [`crate::refine::env::Env`])
14+
/// to build a [`chc::ClauseBuilder`] equipped with in-scope variables and assumptions.
615
pub trait ClauseScope {
716
fn build_clause(&self) -> chc::ClauseBuilder;
817
}
@@ -22,6 +31,7 @@ impl ClauseScope for chc::ClauseBuilder {
2231
}
2332
}
2433

34+
/// Produces CHC constraints for subtyping relations.
2535
pub trait Subtyping {
2636
#[must_use]
2737
fn relate_sub_type<T: chc::Var, U: chc::Var>(

src/rty/template.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
1+
//! "Template" refinement types with unknown predicates to be inferred.
2+
//!
3+
//! A [`Template`] is used to generate a [`RefinedType`] with a refinement consisting of a
4+
//! single atom with a fresh predicate variable. The unknown predicate can carry dependencies,
5+
//! which are the arguments to the predicate. When Thrust infers refinement types, it
6+
//! first generates template refinement types with unknown refinements, and then
7+
//! generates constraints on the predicate variables in these templates.
8+
19
use std::collections::BTreeMap;
210

311
use crate::chc;
412

513
use super::{RefinedType, RefinedTypeVar, Type};
614

15+
/// A template of a refinement type.
16+
///
17+
/// This is a refinement type in the form of `{ T | P(x1, ..., xn) }` where `P` is a
18+
/// predicate variable, `T` is a type, and `x1, ..., xn` are the dependencies. The predicate
19+
/// variable is actually allocated when [`Template::into_refined_type`] is called.
720
#[derive(Debug, Clone)]
821
pub struct Template<FV> {
922
pred_sig: chc::PredSig,
@@ -24,6 +37,11 @@ impl<FV> Template<FV> {
2437
}
2538
}
2639

40+
/// A builder for a [`Template`].
41+
///
42+
/// Note that we have a convenient mechanism in [`crate::refine::template`]
43+
/// to prepare [`TemplateBuilder`] with variables in scope, and we usually don't
44+
/// construct [`TemplateBuilder`] directly.
2745
#[derive(Debug, Clone)]
2846
pub struct TemplateBuilder<FV> {
2947
dependencies: BTreeMap<RefinedTypeVar<FV>, chc::Sort>,

0 commit comments

Comments
 (0)