Skip to content

Commit 7a5e42b

Browse files
authored
Merge pull request #18 from coord-e/std-specs
Inject extern spec of std functions
2 parents bd871bf + 9e74e7a commit 7a5e42b

File tree

8 files changed

+370
-69
lines changed

8 files changed

+370
-69
lines changed

src/analyze.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,6 @@ impl<'tcx> Analyzer<'tcx> {
210210
.variants()
211211
.iter()
212212
.map(|variant| {
213-
let name = refine::datatype_symbol(self.tcx, variant.def_id);
214213
// TODO: consider using TyCtxt::tag_for_variant
215214
let discr = resolve_discr(self.tcx, variant.discr);
216215
let field_tys = variant
@@ -222,7 +221,7 @@ impl<'tcx> Analyzer<'tcx> {
222221
})
223222
.collect();
224223
rty::EnumVariantDef {
225-
name,
224+
name: chc::DatatypeSymbol::new(format!("{}.{}", name, variant.name)),
226225
discr,
227226
field_tys,
228227
}

src/analyze/basic_block.rs

Lines changed: 17 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -562,78 +562,30 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
562562
});
563563
}
564564

565-
fn is_box_new(&self, def_id: DefId) -> bool {
566-
// TODO: stop using diagnositc item for semantic purpose
567-
self.tcx.all_diagnostic_items(()).id_to_name.get(&def_id)
568-
== Some(&rustc_span::symbol::sym::box_new)
569-
}
570-
571-
fn is_mem_swap(&self, def_id: DefId) -> bool {
572-
// TODO: stop using diagnositc item for semantic purpose
573-
self.tcx.all_diagnostic_items(()).id_to_name.get(&def_id)
574-
== Some(&rustc_span::symbol::sym::mem_swap)
575-
}
576-
577565
fn type_call<I>(&mut self, func: Operand<'tcx>, args: I, expected_ret: &rty::RefinedType<Var>)
578566
where
579567
I: IntoIterator<Item = Operand<'tcx>>,
580568
{
581569
// TODO: handle const_fn_def on Env side
582-
let func_ty = match func.const_fn_def() {
583-
// TODO: move this to well-known defs?
584-
Some((def_id, args)) if self.is_box_new(def_id) => {
585-
let inner_ty = self
586-
.type_builder
587-
.for_template(&mut self.ctx)
588-
.build(args.type_at(0))
589-
.vacuous();
590-
let param = rty::RefinedType::unrefined(inner_ty.clone());
591-
let ret_term =
592-
chc::Term::box_(chc::Term::var(rty::FunctionParamIdx::from(0_usize)));
593-
let ret = rty::RefinedType::refined_with_term(
594-
rty::PointerType::own(inner_ty).into(),
595-
ret_term,
596-
);
597-
rty::FunctionType::new([param].into_iter().collect(), ret).into()
598-
}
599-
Some((def_id, args)) if self.is_mem_swap(def_id) => {
600-
let inner_ty = self.type_builder.build(args.type_at(0)).vacuous();
601-
let param1 =
602-
rty::RefinedType::unrefined(rty::PointerType::mut_to(inner_ty.clone()).into());
603-
let param2 =
604-
rty::RefinedType::unrefined(rty::PointerType::mut_to(inner_ty.clone()).into());
605-
let param1_var = rty::RefinedTypeVar::Free(rty::FunctionParamIdx::from(0_usize));
606-
let param2_var = rty::RefinedTypeVar::Free(rty::FunctionParamIdx::from(1_usize));
607-
let ret1 = chc::Term::var(param1_var)
608-
.mut_current()
609-
.equal_to(chc::Term::var(param2_var).mut_final());
610-
let ret2 = chc::Term::var(param2_var)
611-
.mut_current()
612-
.equal_to(chc::Term::var(param1_var).mut_final());
613-
let ret_formula = chc::Formula::Atom(ret1).and(chc::Formula::Atom(ret2));
614-
let ret = rty::RefinedType::new(rty::Type::unit(), ret_formula.into());
615-
rty::FunctionType::new([param1, param2].into_iter().collect(), ret).into()
570+
let func_ty = if let Some((def_id, args)) = func.const_fn_def() {
571+
let param_env = self.tcx.param_env(self.local_def_id);
572+
let instance = mir_ty::Instance::resolve(self.tcx, param_env, def_id, args).unwrap();
573+
let resolved_def_id = if let Some(instance) = instance {
574+
instance.def_id()
575+
} else {
576+
def_id
577+
};
578+
if def_id != resolved_def_id {
579+
tracing::info!(?def_id, ?resolved_def_id, "resolve",);
616580
}
617-
Some((def_id, args)) => {
618-
let param_env = self.tcx.param_env(self.local_def_id);
619-
let instance =
620-
mir_ty::Instance::resolve(self.tcx, param_env, def_id, args).unwrap();
621-
let resolved_def_id = if let Some(instance) = instance {
622-
instance.def_id()
623-
} else {
624-
def_id
625-
};
626-
if def_id != resolved_def_id {
627-
tracing::info!(?def_id, ?resolved_def_id, "resolve",);
628-
}
629581

630-
self.ctx
631-
.def_ty_with_args(resolved_def_id, args)
632-
.expect("unknown def")
633-
.ty
634-
.vacuous()
635-
}
636-
_ => self.operand_type(func.clone()).ty,
582+
self.ctx
583+
.def_ty_with_args(resolved_def_id, args)
584+
.expect("unknown def")
585+
.ty
586+
.vacuous()
587+
} else {
588+
self.operand_type(func.clone()).ty
637589
};
638590
let expected_args: IndexVec<_, _> = args
639591
.into_iter()

src/analyze/local_def.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,13 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
274274
let typeck_result = self.tcx.typeck(self.outer_def_id);
275275
if let rustc_hir::def::Res::Def(_, def_id) = typeck_result.qpath_res(qpath, hir_id)
276276
{
277-
assert!(self.inner_def_id.is_none(), "invalid extern_spec_fn");
278-
self.inner_def_id = Some(def_id);
277+
if matches!(
278+
self.tcx.def_kind(def_id),
279+
rustc_hir::def::DefKind::Fn | rustc_hir::def::DefKind::AssocFn
280+
) {
281+
assert!(self.inner_def_id.is_none(), "invalid extern_spec_fn");
282+
self.inner_def_id = Some(def_id);
283+
}
279284
}
280285
}
281286
}

src/chc.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ impl DatatypeSort {
7878
pub fn new(symbol: DatatypeSymbol, args: Vec<Sort>) -> Self {
7979
DatatypeSort { symbol, args }
8080
}
81+
82+
pub fn args_mut(&mut self) -> &mut Vec<Sort> {
83+
&mut self.args
84+
}
8185
}
8286

8387
/// A sort is the type of a logical term.

src/main.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
#![feature(rustc_private)]
22

3+
extern crate rustc_ast;
34
extern crate rustc_driver;
45
extern crate rustc_interface;
6+
extern crate rustc_parse;
57
extern crate rustc_session;
8+
extern crate rustc_span;
69

710
use rustc_driver::{Callbacks, Compilation, RunCompiler};
811
use rustc_interface::interface::{Compiler, Config};
@@ -17,6 +20,29 @@ impl Callbacks for CompilerCalls {
1720
attrs.push("register_tool(thrust)".to_owned());
1821
}
1922

23+
fn after_crate_root_parsing<'tcx>(
24+
&mut self,
25+
compiler: &Compiler,
26+
queries: &'tcx Queries<'tcx>,
27+
) -> Compilation {
28+
let mut result = queries.parse().unwrap();
29+
let krate = result.get_mut();
30+
31+
let injected = include_str!("../std.rs");
32+
let mut parser = rustc_parse::new_parser_from_source_str(
33+
&compiler.sess.psess,
34+
rustc_span::FileName::Custom("thrust std injected".to_string()),
35+
injected.to_owned(),
36+
);
37+
while let Some(item) = parser
38+
.parse_item(rustc_parse::parser::ForceCollect::No)
39+
.unwrap()
40+
{
41+
krate.items.push(item);
42+
}
43+
Compilation::Continue
44+
}
45+
2046
fn after_analysis<'tcx>(
2147
&mut self,
2248
_compiler: &Compiler,

src/refine/template.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,8 @@ where
412412
.with_scope(&builder)
413413
.build_refined(param_ty.ty)
414414
}
415+
} else if self.param_refinement.is_some() {
416+
rty::RefinedType::unrefined(self.inner.build(param_ty.ty).vacuous())
415417
} else {
416418
rty::RefinedType::unrefined(
417419
self.inner

src/rty.rs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,6 +1254,13 @@ impl<FV> Refinement<FV> {
12541254
refinement: self,
12551255
}
12561256
}
1257+
1258+
pub fn subst_ty_params_in_sorts<T>(&mut self, subst: &TypeParamSubst<T>) {
1259+
for sort in &mut self.existentials {
1260+
subst_ty_params_in_sort(sort, subst);
1261+
}
1262+
subst_ty_params_in_body(&mut self.body, subst);
1263+
}
12571264
}
12581265

12591266
/// A helper type to map logical variables in a refinement at once.
@@ -1445,6 +1452,7 @@ impl<FV> RefinedType<FV> {
14451452
where
14461453
FV: chc::Var,
14471454
{
1455+
self.refinement.subst_ty_params_in_sorts(subst);
14481456
match &mut self.ty {
14491457
Type::Int | Type::Bool | Type::String | Type::Never => {}
14501458
Type::Param(ty) => {
@@ -1513,6 +1521,108 @@ impl RefinedType<Closed> {
15131521
}
15141522
}
15151523

1524+
/// Substitutes type parameters in a sort.
1525+
fn subst_ty_params_in_sort<T>(sort: &mut chc::Sort, subst: &TypeParamSubst<T>) {
1526+
match sort {
1527+
chc::Sort::Null | chc::Sort::Int | chc::Sort::Bool | chc::Sort::String => {}
1528+
chc::Sort::Param(idx) => {
1529+
let type_param_idx = TypeParamIdx::from_usize(*idx);
1530+
if let Some(rty) = subst.get(type_param_idx) {
1531+
*sort = rty.ty.to_sort();
1532+
}
1533+
}
1534+
chc::Sort::Box(s) | chc::Sort::Mut(s) => {
1535+
subst_ty_params_in_sort(s, subst);
1536+
}
1537+
chc::Sort::Tuple(sorts) => {
1538+
for s in sorts {
1539+
subst_ty_params_in_sort(s, subst);
1540+
}
1541+
}
1542+
chc::Sort::Datatype(dt_sort) => {
1543+
for s in dt_sort.args_mut() {
1544+
subst_ty_params_in_sort(s, subst);
1545+
}
1546+
}
1547+
}
1548+
}
1549+
1550+
/// Substitutes type parameters in all sorts appearing in a body.
1551+
fn subst_ty_params_in_body<T, V>(body: &mut chc::Body<V>, subst: &TypeParamSubst<T>) {
1552+
for atom in &mut body.atoms {
1553+
subst_ty_params_in_atom(atom, subst);
1554+
}
1555+
subst_ty_params_in_formula(&mut body.formula, subst);
1556+
}
1557+
1558+
/// Substitutes type parameters in all sorts appearing in an atom.
1559+
fn subst_ty_params_in_atom<T, V>(atom: &mut chc::Atom<V>, subst: &TypeParamSubst<T>) {
1560+
if let Some(guard) = &mut atom.guard {
1561+
subst_ty_params_in_formula(guard, subst);
1562+
}
1563+
for term in &mut atom.args {
1564+
subst_ty_params_in_term(term, subst);
1565+
}
1566+
}
1567+
1568+
/// Substitutes type parameters in all sorts appearing in a formula.
1569+
fn subst_ty_params_in_formula<T, V>(formula: &mut chc::Formula<V>, subst: &TypeParamSubst<T>) {
1570+
match formula {
1571+
chc::Formula::Atom(atom) => subst_ty_params_in_atom(atom, subst),
1572+
chc::Formula::Not(f) => subst_ty_params_in_formula(f, subst),
1573+
chc::Formula::And(fs) | chc::Formula::Or(fs) => {
1574+
for f in fs {
1575+
subst_ty_params_in_formula(f, subst);
1576+
}
1577+
}
1578+
chc::Formula::Exists(vars, f) => {
1579+
for (_, sort) in vars {
1580+
subst_ty_params_in_sort(sort, subst);
1581+
}
1582+
subst_ty_params_in_formula(f, subst);
1583+
}
1584+
}
1585+
}
1586+
1587+
/// Substitutes type parameters in all sorts appearing in a term.
1588+
fn subst_ty_params_in_term<T, V>(term: &mut chc::Term<V>, subst: &TypeParamSubst<T>) {
1589+
match term {
1590+
chc::Term::Null
1591+
| chc::Term::Var(_)
1592+
| chc::Term::Bool(_)
1593+
| chc::Term::Int(_)
1594+
| chc::Term::String(_) => {}
1595+
chc::Term::Box(t)
1596+
| chc::Term::BoxCurrent(t)
1597+
| chc::Term::MutCurrent(t)
1598+
| chc::Term::MutFinal(t)
1599+
| chc::Term::TupleProj(t, _)
1600+
| chc::Term::DatatypeDiscr(_, t) => {
1601+
subst_ty_params_in_term(t, subst);
1602+
}
1603+
chc::Term::Mut(t1, t2) => {
1604+
subst_ty_params_in_term(t1, subst);
1605+
subst_ty_params_in_term(t2, subst);
1606+
}
1607+
chc::Term::App(_, args) | chc::Term::Tuple(args) => {
1608+
for arg in args {
1609+
subst_ty_params_in_term(arg, subst);
1610+
}
1611+
}
1612+
chc::Term::DatatypeCtor(s, _, args) => {
1613+
for arg in s.args_mut() {
1614+
subst_ty_params_in_sort(arg, subst);
1615+
}
1616+
for arg in args {
1617+
subst_ty_params_in_term(arg, subst);
1618+
}
1619+
}
1620+
chc::Term::FormulaExistentialVar(sort, _) => {
1621+
subst_ty_params_in_sort(sort, subst);
1622+
}
1623+
}
1624+
}
1625+
15161626
pub fn unify_tys_params<I1, I2, T>(tys1: I1, tys2: I2) -> TypeParamSubst<T>
15171627
where
15181628
T: chc::Var,

0 commit comments

Comments
 (0)