Skip to content

Commit 85e48e2

Browse files
committed
Enable to type closure calls
1 parent 9f07545 commit 85e48e2

3 files changed

Lines changed: 69 additions & 4 deletions

File tree

src/analyze/basic_block.rs

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,54 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
8484
) -> Vec<chc::Clause> {
8585
let mut clauses = Vec::new();
8686

87-
if expected_args.is_empty() {
88-
// elaboration: we need at least one predicate variable in parameter (see mir_function_ty_impl)
89-
expected_args.push(rty::RefinedType::unrefined(rty::Type::unit()).vacuous());
90-
}
9187
tracing::debug!(
9288
got = %got.display(),
9389
expected = %crate::pretty::FunctionType::new(&expected_args, &expected_ret).display(),
9490
"fn_sub_type"
9591
);
9692

93+
match got.abi {
94+
rty::FunctionAbi::Rust => {
95+
if expected_args.is_empty() {
96+
// elaboration: we need at least one predicate variable in parameter (see mir_function_ty_impl)
97+
expected_args.push(rty::RefinedType::unrefined(rty::Type::unit()).vacuous());
98+
}
99+
}
100+
rty::FunctionAbi::RustCall => {
101+
// &Closure, { v: (own i32, own bool) | v = (<0>, <false>) }
102+
// =>
103+
// &Closure, { v: i32 | (<v>, _) = (<0>, <false>) }, { v: bool | (_, <v>) = (<0>, <false>) }
104+
105+
let rty::RefinedType { ty, mut refinement } =
106+
expected_args.pop().expect("rust-call last arg");
107+
let ty = ty.into_tuple().expect("rust-call last arg is tuple");
108+
let mut replacement_tuple = Vec::new(); // will be (<v>, _) or (_, <v>)
109+
for elem in &ty.elems {
110+
let existential = refinement.existentials.push(elem.ty.to_sort());
111+
replacement_tuple.push(chc::Term::var(rty::RefinedTypeVar::Existential(
112+
existential,
113+
)));
114+
}
115+
116+
for (i, elem) in ty.elems.into_iter().enumerate() {
117+
let mut param_ty = elem.deref();
118+
param_ty
119+
.refinement
120+
.push_conj(refinement.clone().subst_value_var(|| {
121+
let mut value_elems = replacement_tuple.clone();
122+
value_elems[i] = chc::Term::var(rty::RefinedTypeVar::Value).boxed();
123+
chc::Term::tuple(value_elems)
124+
}));
125+
expected_args.push(param_ty);
126+
}
127+
128+
tracing::info!(
129+
expected = %crate::pretty::FunctionType::new(&expected_args, &expected_ret).display(),
130+
"rust-call expanded",
131+
);
132+
}
133+
}
134+
97135
// TODO: check sty and length is equal
98136
let mut builder = self.env.build_clause();
99137
for (param_idx, param_rty) in got.params.iter_enumerated() {

src/chc.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,10 @@ impl<V> Term<V> {
616616
Term::Mut(Box::new(t1), Box::new(t2))
617617
}
618618

619+
pub fn boxed(self) -> Self {
620+
Term::Box(Box::new(self))
621+
}
622+
619623
pub fn box_current(self) -> Self {
620624
Term::BoxCurrent(Box::new(self))
621625
}

src/rty.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,6 +1356,29 @@ impl<FV> RefinedType<FV> {
13561356
RefinedType { ty, refinement }
13571357
}
13581358

1359+
pub fn deref(self) -> Self {
1360+
let RefinedType {
1361+
ty,
1362+
refinement: outer_refinement,
1363+
} = self;
1364+
let inner_ty = ty.into_pointer().expect("invalid deref");
1365+
if inner_ty.is_mut() {
1366+
// losing info about proph
1367+
panic!("invalid deref");
1368+
}
1369+
let RefinedType {
1370+
ty: inner_ty,
1371+
refinement: mut inner_refinement,
1372+
} = *inner_ty.elem;
1373+
inner_refinement.push_conj(
1374+
outer_refinement.subst_value_var(|| chc::Term::var(RefinedTypeVar::Value).boxed()),
1375+
);
1376+
RefinedType {
1377+
ty: inner_ty,
1378+
refinement: inner_refinement,
1379+
}
1380+
}
1381+
13591382
pub fn subst_var<F, W>(self, mut f: F) -> RefinedType<W>
13601383
where
13611384
F: FnMut(FV) -> chc::Term<W>,

0 commit comments

Comments
 (0)