Skip to content

Commit dbaaf26

Browse files
authored
Merge pull request #5 from coord-e/doc-some
Add documentation to rty and some other modules
2 parents f0ddfed + 485112c commit dbaaf26

12 files changed

Lines changed: 202 additions & 2 deletions

File tree

src/analyze.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
//! Analysis of Rust MIR to generate a CHC system.
2+
//!
3+
//! The [`Analyzer`] generates subtyping constraints in the form of CHCs ([`chc::System`]).
4+
//! The entry point is [`crate_::Analyzer::run`], followed by [`local_def::Analyzer::run`]
5+
//! and [`basic_block::Analyzer::run`], while accumulating the necessary information in
6+
//! [`Analyzer`]. Once [`chc::System`] is collected for the entire input, it invokes an external
7+
//! CHC solver with the [`Analyzer::solve`] and subsequently reports the result.
8+
19
use std::cell::RefCell;
210
use std::collections::HashMap;
311
use std::rc::Rc;

src/analyze/annot.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Supporting implementation for parsing Thrust annotations.
2+
13
use rustc_ast::ast::Attribute;
24
use rustc_ast::tokenstream::TokenStream;
35
use rustc_index::IndexVec;
@@ -31,6 +33,10 @@ pub fn callable_path() -> [Symbol; 2] {
3133
[Symbol::intern("thrust"), Symbol::intern("callable")]
3234
}
3335

36+
/// A [`annot::Resolver`] implementation for resolving function parameters.
37+
///
38+
/// The parameter names and their sorts needs to be configured via
39+
/// [`ParamResolver::push_param`] before use.
3440
#[derive(Debug, Clone, Default)]
3541
pub struct ParamResolver {
3642
params: IndexVec<rty::FunctionParamIdx, (Symbol, chc::Sort)>,
@@ -52,6 +58,10 @@ impl ParamResolver {
5258
}
5359
}
5460

61+
/// A [`annot::Resolver`] implementation for resolving the special identifier `result`.
62+
///
63+
/// The `result` identifier is used to refer to [`rty::RefinedTypeVar::Value`] in postconditions, denoting
64+
/// the return value of a function.
5565
#[derive(Debug, Clone)]
5666
pub struct ResultResolver {
5767
result_symbol: Symbol,

src/analyze/crate_.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Analyze a local crate.
2+
13
use std::collections::HashSet;
24

35
use rustc_hir::def::DefKind;
@@ -12,6 +14,16 @@ use crate::chc;
1214
use crate::refine::{self, TemplateTypeGenerator, UnrefinedTypeGenerator};
1315
use crate::rty::{self, ClauseBuilderExt as _};
1416

17+
/// An implementation of local crate analysis.
18+
///
19+
/// The entry point is [`Analyzer::run`], which performs the following steps in order:
20+
///
21+
/// 1. Register enum definitions found in the crate.
22+
/// 2. Give initial refinement types to local function definitions based on their signatures and
23+
/// annotations. This generates template refinement types with predicate variables for parameters and
24+
/// return types that are not known via annotations.
25+
/// 3. Type local function definition bodies via [`super::local_def::Analyzer`] using the refinement types
26+
/// generated in the previous step.
1527
pub struct Analyzer<'tcx, 'ctx> {
1628
tcx: TyCtxt<'tcx>,
1729
ctx: &'ctx mut analyze::Analyzer<'tcx>,

src/analyze/did_cache.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Retrieves and caches well-known [`DefId`]s.
2+
13
use std::cell::OnceCell;
24

35
use rustc_middle::ty::TyCtxt;
@@ -10,6 +12,10 @@ struct DefIds {
1012
nonnull: OnceCell<Option<DefId>>,
1113
}
1214

15+
/// Retrieves and caches well-known [`DefId`]s.
16+
///
17+
/// [`DefId`]s of some well-known types can be retrieved as lang items or via the definition of
18+
/// lang items. This struct implements that logic and caches the results.
1319
#[derive(Clone)]
1420
pub struct DefIdCache<'tcx> {
1521
tcx: TyCtxt<'tcx>,

src/analyze/local_def.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Analyze a local definition.
2+
13
use std::collections::{HashMap, HashSet};
24

35
use rustc_index::bit_set::BitSet;
@@ -12,6 +14,10 @@ use crate::pretty::PrettyDisplayExt as _;
1214
use crate::refine::{BasicBlockType, TemplateTypeGenerator};
1315
use crate::rty;
1416

17+
/// An implementation of the typing of local definitions.
18+
///
19+
/// The current implementation only applies to function definitions. The entry point is
20+
/// [`Analyzer::run`], which generates constraints during typing, given the expected type of the function.
1521
pub struct Analyzer<'tcx, 'ctx> {
1622
ctx: &'ctx mut analyze::Analyzer<'tcx>,
1723
tcx: TyCtxt<'tcx>,

src/refine.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
//! Core logic of refinement typing.
2+
//!
3+
//! This module includes the definition of the refinement typing environment and the template
4+
//! type generation from MIR types.
5+
//!
6+
//! This module is used by the [`crate::analyze`] module. There is currently no clear boundary between
7+
//! the `analyze` and `refine` modules, so it is a TODO to integrate this into the `analyze`
8+
//! module and remove this one.
9+
110
mod template;
211
pub use template::{TemplateScope, TemplateTypeGenerator, UnrefinedTypeGenerator};
312

src/refine/basic_block.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1+
//! The refinement type for a basic block.
2+
13
use pretty::{termcolor, Pretty};
24
use rustc_index::IndexVec;
35
use rustc_middle::mir::Local;
46
use rustc_middle::ty as mir_ty;
57

68
use crate::rty;
79

8-
/// `BasicBlockType` is a special case of `FunctionType` whose parameters are
9-
/// associated with `Local`s.
10+
/// A special case of [`rty::FunctionType`] whose parameters are associated with [`Local`]s.
11+
///
12+
/// Thrust handles basic blocks as functions, but it needs to associate function
13+
/// parameters with MIR [`Local`]s during its analysis. [`BasicBlockType`] includes this mapping
14+
/// from function parameters to [`Local`]s, along with the underlying function type.
1015
#[derive(Debug, Clone)]
1116
pub struct BasicBlockType {
1217
// TODO: make this completely private by exposing appropriate ctor

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 can 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 [`super::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 [`super::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>,

0 commit comments

Comments
 (0)