Skip to content

Commit f706742

Browse files
committed
Add integration test for unwind safety
1 parent 27a9850 commit f706742

File tree

4 files changed

+187
-4
lines changed

4 files changed

+187
-4
lines changed

tests/integration/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mod panic;

tests/integration/panic.rs

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
use chalk_integration::db::ChalkDatabase;
2+
use chalk_integration::query::LoweringDatabase;
3+
use chalk_ir::interner::ChalkIr;
4+
use chalk_ir::AssocTypeId;
5+
use chalk_ir::Goal;
6+
use chalk_ir::ImplId;
7+
use chalk_ir::InEnvironment;
8+
use chalk_ir::OpaqueTyId;
9+
use chalk_ir::Parameter;
10+
use chalk_ir::ProgramClause;
11+
use chalk_ir::StructId;
12+
use chalk_ir::TraitId;
13+
use chalk_ir::TypeName;
14+
use chalk_ir::UCanonical;
15+
use chalk_rust_ir::AssociatedTyDatum;
16+
use chalk_rust_ir::AssociatedTyValue;
17+
use chalk_rust_ir::AssociatedTyValueId;
18+
use chalk_rust_ir::ImplDatum;
19+
use chalk_rust_ir::OpaqueTyDatum;
20+
use chalk_rust_ir::StructDatum;
21+
use chalk_rust_ir::TraitDatum;
22+
use chalk_rust_ir::WellKnownTrait;
23+
use chalk_solve::RustIrDatabase;
24+
use chalk_solve::Solution;
25+
use chalk_solve::SolverChoice;
26+
use std::sync::Arc;
27+
28+
#[derive(Debug, Default)]
29+
struct MockDatabase {
30+
chalk_db: ChalkDatabase,
31+
panic: bool,
32+
}
33+
34+
impl MockDatabase {
35+
pub fn with(program_text: &str, solver_choice: SolverChoice) -> Self {
36+
Self {
37+
chalk_db: ChalkDatabase::with(program_text, solver_choice),
38+
panic: false,
39+
}
40+
}
41+
42+
pub fn solve(
43+
&self,
44+
goal: &UCanonical<InEnvironment<Goal<ChalkIr>>>,
45+
) -> Option<Solution<ChalkIr>> {
46+
let solver = self.chalk_db.solver();
47+
let solution = solver.lock().unwrap().solve(self, goal);
48+
solution
49+
}
50+
}
51+
52+
impl RustIrDatabase<ChalkIr> for MockDatabase {
53+
fn custom_clauses(&self) -> Vec<ProgramClause<ChalkIr>> {
54+
if self.panic {
55+
unimplemented!()
56+
} else {
57+
self.chalk_db.custom_clauses()
58+
}
59+
}
60+
61+
fn associated_ty_data(&self, ty: AssocTypeId<ChalkIr>) -> Arc<AssociatedTyDatum<ChalkIr>> {
62+
self.chalk_db.associated_ty_data(ty)
63+
}
64+
65+
fn trait_datum(&self, id: TraitId<ChalkIr>) -> Arc<TraitDatum<ChalkIr>> {
66+
self.chalk_db.trait_datum(id)
67+
}
68+
69+
fn impl_datum(&self, id: ImplId<ChalkIr>) -> Arc<ImplDatum<ChalkIr>> {
70+
self.chalk_db.impl_datum(id)
71+
}
72+
73+
fn associated_ty_value(
74+
&self,
75+
id: AssociatedTyValueId<ChalkIr>,
76+
) -> Arc<AssociatedTyValue<ChalkIr>> {
77+
self.chalk_db.associated_ty_value(id)
78+
}
79+
80+
fn opaque_ty_data(&self, id: OpaqueTyId<ChalkIr>) -> Arc<OpaqueTyDatum<ChalkIr>> {
81+
self.chalk_db.opaque_ty_data(id)
82+
}
83+
84+
fn struct_datum(&self, id: StructId<ChalkIr>) -> Arc<StructDatum<ChalkIr>> {
85+
self.chalk_db.struct_datum(id)
86+
}
87+
88+
fn as_struct_id(&self, type_name: &TypeName<ChalkIr>) -> Option<StructId<ChalkIr>> {
89+
self.chalk_db.as_struct_id(type_name)
90+
}
91+
92+
fn impls_for_trait(
93+
&self,
94+
trait_id: TraitId<ChalkIr>,
95+
parameters: &[Parameter<ChalkIr>],
96+
) -> Vec<ImplId<ChalkIr>> {
97+
self.chalk_db.impls_for_trait(trait_id, parameters)
98+
}
99+
100+
fn local_impls_to_coherence_check(&self, trait_id: TraitId<ChalkIr>) -> Vec<ImplId<ChalkIr>> {
101+
self.chalk_db.local_impls_to_coherence_check(trait_id)
102+
}
103+
104+
fn impl_provided_for(
105+
&self,
106+
auto_trait_id: TraitId<ChalkIr>,
107+
struct_id: StructId<ChalkIr>,
108+
) -> bool {
109+
self.chalk_db.impl_provided_for(auto_trait_id, struct_id)
110+
}
111+
112+
fn well_known_trait_id(&self, well_known_trait: WellKnownTrait) -> Option<TraitId<ChalkIr>> {
113+
self.chalk_db.well_known_trait_id(well_known_trait)
114+
}
115+
116+
fn interner(&self) -> &ChalkIr {
117+
&ChalkIr
118+
}
119+
}
120+
121+
#[test]
122+
fn unwind_safety() {
123+
use self::MockDatabase;
124+
use chalk_integration::lowering::LowerGoal;
125+
use chalk_integration::query::LoweringDatabase;
126+
use chalk_solve::ext::GoalExt;
127+
use std::panic;
128+
129+
// lower program
130+
let mut db = lower_program_with_db! {
131+
program {
132+
struct Foo { }
133+
trait Bar { }
134+
impl Bar for Foo { }
135+
}
136+
database MockDatabase
137+
};
138+
139+
let program = db.chalk_db.checked_program().unwrap();
140+
141+
// lower goal
142+
let goal = lower_goal! {
143+
goal {
144+
Foo: Bar
145+
}
146+
program &*program
147+
};
148+
let peeled_goal = goal.into_peeled_goal(db.interner());
149+
150+
// solve goal but this will panic
151+
db.panic = true;
152+
let result = panic::catch_unwind(|| {
153+
db.solve(&peeled_goal);
154+
});
155+
assert!(result.is_err() == true);
156+
157+
// solve again but without panicking this time
158+
db.panic = false;
159+
assert!(db.solve(&peeled_goal).is_some());
160+
}

tests/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ mod test_util;
44
mod test;
55

66
mod lowering;
7+
8+
mod integration;

tests/test_util.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,35 @@
11
#![allow(unused_macros)]
22

3-
macro_rules! lowering_success {
4-
(program $program:tt) => {
3+
macro_rules! lower_program_with_db {
4+
(program $program:tt database $database:ty) => {{
55
let program_text = stringify!($program);
66
assert!(program_text.starts_with("{"));
77
assert!(program_text.ends_with("}"));
8-
let result = chalk_integration::db::ChalkDatabase::with(
8+
<$database>::with(
99
&program_text[1..program_text.len() - 1],
1010
chalk_solve::SolverChoice::default(),
1111
)
12-
.checked_program();
12+
}};
13+
}
14+
15+
macro_rules! lower_goal {
16+
(goal $goal:tt program $program:expr) => {{
17+
let goal_text = stringify!($goal);
18+
assert!(goal_text.starts_with("{"));
19+
assert!(goal_text.ends_with("}"));
20+
chalk_parse::parse_goal(&goal_text[1..goal_text.len() - 1])
21+
.unwrap()
22+
.lower($program)
23+
.unwrap()
24+
}};
25+
}
26+
27+
macro_rules! lowering_success {
28+
(program $program:tt) => {
29+
let result = lower_program_with_db!(
30+
program $program
31+
database chalk_integration::db::ChalkDatabase
32+
).checked_program();
1333
if let Err(ref e) = result {
1434
println!("lowering error: {}", e);
1535
}

0 commit comments

Comments
 (0)