Skip to content

Commit ae3268c

Browse files
committed
Drop old token-based annotation parser (closes #70)
Remove src/annot.rs (the 1355-line token-based annotation parser) and all code that depended on it. All annotation parsing now goes through the formula_fn mechanism introduced in #57. - Delete src/annot.rs entirely - Simplify extract_require_annot / extract_ensure_annot to use formula_fn paths only, dropping the Resolver generic and self_type_name arguments - Remove extract_param_annots / extract_ret_annot from local_def::Analyzer (param/ret are now handled via refinement_path formula fns from #98) - Remove ParamResolver, ResultResolver, split_param from analyze/annot.rs - Update is_fully_annotated to check requires_path / ensures_path only - Remove the dual-predicate-name workaround in analyze_predicate_definition that existed solely to support the old parser's string-based name lookup - Drop dead helpers: requires_path, ensures_path, param_path, ret_path, param_rty, ret_rty, impl_type https://claude.ai/code/session_01VBt3rgWkzGRyWMV7hfCY6i
1 parent 5648fd2 commit ae3268c

7 files changed

Lines changed: 58 additions & 1750 deletions

File tree

src/analyze.rs

Lines changed: 34 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use rustc_span::def_id::{DefId, LocalDefId};
1818
use rustc_span::Symbol;
1919

2020
use crate::analyze;
21-
use crate::annot::{AnnotFormula, AnnotParser, Resolver};
2221
use crate::chc;
2322
use crate::pretty::PrettyDisplayExt as _;
2423
use crate::refine::{self, BasicBlockType, TypeBuilder};
@@ -745,103 +744,48 @@ impl<'tcx> Analyzer<'tcx> {
745744
None
746745
}
747746

748-
// TODO: reduce number of args
749-
fn extract_require_annot<T>(
747+
fn extract_require_annot(
750748
&self,
751749
local_def_id: LocalDefId,
752-
resolver: T,
753-
self_type_name: Option<String>,
754750
generic_args: mir_ty::GenericArgsRef<'tcx>,
755-
) -> Option<AnnotFormula<T::Output>>
756-
where
757-
T: Resolver<Output = rty::FunctionParamIdx>,
758-
{
759-
let mut require_annot = None;
760-
let parser = AnnotParser::new(&resolver, self_type_name);
761-
for attrs in self
762-
.tcx
763-
.get_attrs_by_path(local_def_id.to_def_id(), &analyze::annot::requires_path())
764-
{
765-
if require_annot.is_some() {
766-
unimplemented!();
767-
}
768-
let ts = analyze::annot::extract_annot_tokens(attrs.clone());
769-
let require = parser.parse_formula(ts).unwrap();
770-
require_annot = Some(require);
771-
}
772-
773-
if let Some(formula_def_id) =
774-
self.extract_path_with_attr(local_def_id, &analyze::annot::requires_path_path())
775-
{
776-
let Some(formula_def_id) = formula_def_id.as_local() else {
777-
panic!(
778-
"require annotation with path is expected to refer to a local def, but found: {:?}",
779-
formula_def_id
780-
);
781-
};
782-
if require_annot.is_some() {
783-
unimplemented!();
784-
}
785-
let Some(formula_fn) = self.formula_fn_with_args(formula_def_id, generic_args) else {
786-
panic!(
787-
"require annotation {:?} is not a formula function",
788-
formula_def_id
789-
);
790-
};
791-
require_annot = Some(formula_fn.to_require_annot());
792-
}
793-
794-
require_annot
751+
) -> Option<chc::Formula<rty::FunctionParamIdx>> {
752+
let formula_def_id =
753+
self.extract_path_with_attr(local_def_id, &analyze::annot::requires_path_path())?;
754+
let Some(formula_def_id) = formula_def_id.as_local() else {
755+
panic!(
756+
"require annotation with path is expected to refer to a local def, but found: {:?}",
757+
formula_def_id
758+
);
759+
};
760+
let Some(formula_fn) = self.formula_fn_with_args(formula_def_id, generic_args) else {
761+
panic!(
762+
"require annotation {:?} is not a formula function",
763+
formula_def_id
764+
);
765+
};
766+
Some(formula_fn.to_require_formula())
795767
}
796768

797-
// TODO: reduce number of args
798-
fn extract_ensure_annot<T>(
769+
fn extract_ensure_annot(
799770
&self,
800771
local_def_id: LocalDefId,
801-
resolver: T,
802-
self_type_name: Option<String>,
803772
generic_args: mir_ty::GenericArgsRef<'tcx>,
804-
) -> Option<AnnotFormula<T::Output>>
805-
where
806-
T: Resolver<Output = rty::RefinedTypeVar<rty::FunctionParamIdx>>,
807-
{
808-
let mut ensure_annot = None;
809-
810-
let parser = AnnotParser::new(&resolver, self_type_name);
811-
for attrs in self
812-
.tcx
813-
.get_attrs_by_path(local_def_id.to_def_id(), &analyze::annot::ensures_path())
814-
{
815-
if ensure_annot.is_some() {
816-
unimplemented!();
817-
}
818-
let ts = analyze::annot::extract_annot_tokens(attrs.clone());
819-
let ensure = parser.parse_formula(ts).unwrap();
820-
ensure_annot = Some(ensure);
821-
}
822-
823-
if let Some(formula_def_id) =
824-
self.extract_path_with_attr(local_def_id, &analyze::annot::ensures_path_path())
825-
{
826-
let Some(formula_def_id) = formula_def_id.as_local() else {
827-
panic!(
828-
"ensure annotation with path is expected to refer to a local def, but found: {:?}",
829-
formula_def_id
830-
);
831-
};
832-
if ensure_annot.is_some() {
833-
unimplemented!();
834-
}
835-
let Some(formula_fn) = self.formula_fn_with_args(formula_def_id, generic_args) else {
836-
panic!(
837-
"ensure annotation {:?} is not a formula function",
838-
formula_def_id
839-
);
840-
};
841-
ensure_annot = Some(formula_fn.to_ensure_annot());
842-
}
843-
844-
ensure_annot
773+
) -> Option<chc::Formula<rty::RefinedTypeVar<rty::FunctionParamIdx>>> {
774+
let formula_def_id =
775+
self.extract_path_with_attr(local_def_id, &analyze::annot::ensures_path_path())?;
776+
let Some(formula_def_id) = formula_def_id.as_local() else {
777+
panic!(
778+
"ensure annotation with path is expected to refer to a local def, but found: {:?}",
779+
formula_def_id
780+
);
781+
};
782+
let Some(formula_fn) = self.formula_fn_with_args(formula_def_id, generic_args) else {
783+
panic!(
784+
"ensure annotation {:?} is not a formula function",
785+
formula_def_id
786+
);
787+
};
788+
Some(formula_fn.to_ensure_formula())
845789
}
846790

847791
/// Collects every `#[thrust::refinement_path(..)]` path statement in the

src/analyze/annot.rs

Lines changed: 1 addition & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,10 @@
22
33
use rustc_ast::tokenstream::TokenStream;
44
use rustc_hir::Attribute;
5-
use rustc_index::IndexVec;
6-
use rustc_span::symbol::{Ident, Symbol};
5+
use rustc_span::symbol::Symbol;
76

8-
use crate::annot;
9-
use crate::chc;
107
use crate::rty;
118

12-
pub fn requires_path() -> [Symbol; 2] {
13-
[Symbol::intern("thrust"), Symbol::intern("requires")]
14-
}
15-
16-
pub fn ensures_path() -> [Symbol; 2] {
17-
[Symbol::intern("thrust"), Symbol::intern("ensures")]
18-
}
19-
20-
pub fn param_path() -> [Symbol; 2] {
21-
[Symbol::intern("thrust"), Symbol::intern("param")]
22-
}
23-
24-
pub fn ret_path() -> [Symbol; 2] {
25-
[Symbol::intern("thrust"), Symbol::intern("ret")]
26-
}
27-
289
pub fn trusted_path() -> [Symbol; 2] {
2910
[Symbol::intern("thrust"), Symbol::intern("trusted")]
3011
}
@@ -249,62 +230,6 @@ pub fn closure_postcondition_path() -> [Symbol; 3] {
249230
]
250231
}
251232

252-
/// A [`annot::Resolver`] implementation for resolving function parameters.
253-
///
254-
/// The parameter names and their sorts needs to be configured via
255-
/// [`ParamResolver::push_param`] before use.
256-
#[derive(Debug, Clone, Default)]
257-
pub struct ParamResolver {
258-
params: IndexVec<rty::FunctionParamIdx, (Symbol, chc::Sort)>,
259-
}
260-
261-
impl annot::Resolver for ParamResolver {
262-
type Output = rty::FunctionParamIdx;
263-
fn resolve(&self, ident: Ident) -> Option<(Self::Output, chc::Sort)> {
264-
self.params
265-
.iter_enumerated()
266-
.find(|(_, (name, _))| name == &ident.name)
267-
.map(|(idx, (_, sort))| (idx, sort.clone()))
268-
}
269-
}
270-
271-
impl ParamResolver {
272-
pub fn push_param(&mut self, name: Symbol, sort: chc::Sort) {
273-
self.params.push((name, sort));
274-
}
275-
}
276-
277-
/// A [`annot::Resolver`] implementation for resolving the special identifier `result`.
278-
///
279-
/// The `result` identifier is used to refer to [`rty::RefinedTypeVar::Value`] in postconditions, denoting
280-
/// the return value of a function.
281-
#[derive(Debug, Clone)]
282-
pub struct ResultResolver {
283-
result_symbol: Symbol,
284-
result_sort: chc::Sort,
285-
}
286-
287-
impl annot::Resolver for ResultResolver {
288-
type Output = rty::RefinedTypeVar<rty::FunctionParamIdx>;
289-
fn resolve(&self, ident: Ident) -> Option<(Self::Output, chc::Sort)> {
290-
if ident.name == self.result_symbol {
291-
Some((rty::RefinedTypeVar::Value, self.result_sort.clone()))
292-
} else {
293-
None
294-
}
295-
}
296-
}
297-
298-
impl ResultResolver {
299-
pub fn new(result_sort: chc::Sort) -> Self {
300-
let result_symbol = Symbol::intern("result");
301-
Self {
302-
result_symbol,
303-
result_sort,
304-
}
305-
}
306-
}
307-
308233
pub fn extract_annot_tokens(attr: Attribute) -> TokenStream {
309234
let Attribute::Unparsed(item) = attr else {
310235
panic!("invalid attribute: expected unparsed");
@@ -368,18 +293,3 @@ pub fn parse_type_position(ts: &TokenStream) -> rty::TypePosition {
368293
rty::TypePosition::new(steps)
369294
}
370295

371-
pub fn split_param(ts: &TokenStream) -> (Ident, TokenStream) {
372-
use rustc_ast::token::TokenKind;
373-
use rustc_ast::tokenstream::TokenTree;
374-
375-
let mut iter = ts.iter();
376-
let (ident, _) = match iter.next() {
377-
Some(TokenTree::Token(t, _)) => t.ident().expect("expected parameter name"),
378-
_ => panic!("expected parameter name"),
379-
};
380-
match iter.next() {
381-
Some(TokenTree::Token(t, _)) if t.kind == TokenKind::Colon => {}
382-
_ => panic!("expected :"),
383-
}
384-
(ident, iter.cloned().collect())
385-
}

src/analyze/annot_fn.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use rustc_index::IndexVec;
66
use rustc_middle::ty::{self as mir_ty, TyCtxt};
77

88
use crate::analyze::{self, did_cache::DefIdCache};
9-
use crate::annot::AnnotFormula;
109
use crate::chc;
1110
use crate::refine::{self, TypeBuilder};
1211
use crate::rty;
@@ -44,24 +43,24 @@ impl<'tcx> FormulaFn<'tcx> {
4443
&self.formula
4544
}
4645

47-
pub fn to_require_annot(&self) -> AnnotFormula<rty::FunctionParamIdx> {
48-
AnnotFormula::Formula(self.formula.clone())
46+
pub fn to_require_formula(&self) -> chc::Formula<rty::FunctionParamIdx> {
47+
self.formula.clone()
4948
}
5049

51-
/// Lowers an `ensures` formula function into a postcondition annotation.
50+
/// Lowers an `ensures` formula function into a postcondition formula.
5251
///
5352
/// Relies on the layout produced by `thrust_macros::ensures`: parameter `0`
5453
/// is the function's return value (bound to [`rty::RefinedTypeVar::Value`])
5554
/// and parameters `1..n` are the enclosing function's parameters in order
5655
/// (mapped to [`rty::RefinedTypeVar::Free`]).
57-
pub fn to_ensure_annot(&self) -> AnnotFormula<rty::RefinedTypeVar<rty::FunctionParamIdx>> {
58-
AnnotFormula::Formula(self.formula.clone().map_var(|v| {
56+
pub fn to_ensure_formula(&self) -> chc::Formula<rty::RefinedTypeVar<rty::FunctionParamIdx>> {
57+
self.formula.clone().map_var(|v| {
5958
if v.as_usize() == 0 {
6059
rty::RefinedTypeVar::Value
6160
} else {
6261
rty::RefinedTypeVar::Free(rty::FunctionParamIdx::from(v.as_usize() - 1))
6362
}
64-
}))
63+
})
6564
}
6665

6766
/// Lowers a refinement-type formula function (generated by the `param` /

0 commit comments

Comments
 (0)