@@ -4,26 +4,53 @@ use chalk_rust_ir::*;
4
4
use chalk_solve:: { RustIrDatabase , SolverChoice } ;
5
5
use std:: sync:: Arc ;
6
6
7
+ #[ derive( Debug ) ]
8
+ enum PanickingMethod {
9
+ NoPanic ,
10
+ CustomClauses ,
11
+ TraitDatum ,
12
+ ImplDatum ,
13
+ ImplsForTrait ,
14
+ ProgramClausesForEnv ,
15
+ Interner ,
16
+ }
17
+
18
+ impl Default for PanickingMethod {
19
+ fn default ( ) -> Self {
20
+ Self :: NoPanic
21
+ }
22
+ }
23
+
7
24
#[ derive( Debug , Default ) ]
8
25
struct MockDatabase {
9
- panic : bool ,
26
+ panicking_method : PanickingMethod ,
10
27
}
11
28
29
+ /// This DB is representint lowered program:
30
+ ///
31
+ /// struct Foo { }
32
+ /// trait Bar { }
33
+ /// impl Bar for Foo { }
12
34
#[ allow( unused_variables) ]
13
35
impl RustIrDatabase < ChalkIr > for MockDatabase {
14
36
fn custom_clauses ( & self ) -> Vec < ProgramClause < ChalkIr > > {
15
- if self . panic {
16
- panic ! ( "test panic" ) ;
17
- } else {
18
- vec ! [ ]
37
+ if let PanickingMethod :: CustomClauses = self . panicking_method {
38
+ panic ! ( "custom_clauses panic" ) ;
19
39
}
40
+
41
+ vec ! [ ]
20
42
}
21
43
22
44
fn associated_ty_data ( & self , ty : AssocTypeId < ChalkIr > ) -> Arc < AssociatedTyDatum < ChalkIr > > {
23
45
unimplemented ! ( )
24
46
}
25
47
48
+ // `trait Bar`, id `0`
26
49
fn trait_datum ( & self , id : TraitId < ChalkIr > ) -> Arc < TraitDatum < ChalkIr > > {
50
+ if let PanickingMethod :: TraitDatum = self . panicking_method {
51
+ panic ! ( "trait_datum panic" ) ;
52
+ }
53
+
27
54
assert_eq ! ( id. 0 . index, 0 ) ;
28
55
Arc :: new ( chalk_rust_ir:: TraitDatum {
29
56
id,
@@ -46,7 +73,12 @@ impl RustIrDatabase<ChalkIr> for MockDatabase {
46
73
} )
47
74
}
48
75
76
+ // `impl Bar for Foo`, id `1`
49
77
fn impl_datum ( & self , id : ImplId < ChalkIr > ) -> Arc < ImplDatum < ChalkIr > > {
78
+ if let PanickingMethod :: ImplDatum = self . panicking_method {
79
+ panic ! ( "impl_datum panic" ) ;
80
+ }
81
+
50
82
assert_eq ! ( id. 0 . index, 1 ) ;
51
83
52
84
let substitution = Ty :: new (
@@ -95,11 +127,16 @@ impl RustIrDatabase<ChalkIr> for MockDatabase {
95
127
unimplemented ! ( )
96
128
}
97
129
130
+ // All `Bar` impls
98
131
fn impls_for_trait (
99
132
& self ,
100
133
trait_id : TraitId < ChalkIr > ,
101
134
parameters : & [ GenericArg < ChalkIr > ] ,
102
135
) -> Vec < ImplId < ChalkIr > > {
136
+ if let PanickingMethod :: ImplsForTrait = self . panicking_method {
137
+ panic ! ( "impls_for_trait panic" ) ;
138
+ }
139
+
103
140
assert_eq ! ( trait_id. 0 . index, 0 ) ;
104
141
vec ! [ ImplId ( RawId { index: 1 } ) ]
105
142
}
@@ -124,10 +161,18 @@ impl RustIrDatabase<ChalkIr> for MockDatabase {
124
161
& self ,
125
162
environment : & Environment < ChalkIr > ,
126
163
) -> ProgramClauses < ChalkIr > {
164
+ if let PanickingMethod :: ProgramClausesForEnv = self . panicking_method {
165
+ panic ! ( "program_clauses_for_env panic" )
166
+ }
167
+
127
168
ProgramClauses :: new ( & ChalkIr )
128
169
}
129
170
130
171
fn interner ( & self ) -> & ChalkIr {
172
+ if let PanickingMethod :: Interner = self . panicking_method {
173
+ panic ! ( "interner panic" )
174
+ }
175
+
131
176
& ChalkIr
132
177
}
133
178
@@ -136,29 +181,14 @@ impl RustIrDatabase<ChalkIr> for MockDatabase {
136
181
}
137
182
}
138
183
139
- #[ test]
140
- fn unwind_safety ( ) {
141
- use self :: MockDatabase ;
142
- use chalk_integration:: interner:: { self , ChalkIr } ;
184
+ fn prepare_goal ( ) -> UCanonical < InEnvironment < Goal < ChalkIr > > > {
185
+ use chalk_integration:: interner;
143
186
use chalk_ir:: * ;
144
- use std:: panic;
145
-
146
- // lower program
147
- /*
148
- let mut db = lower_program_with_db! {
149
- program {
150
- struct Foo { }
151
- trait Bar { }
152
- impl Bar for Foo { }
153
- }
154
- database MockDatabase
155
- };
156
187
157
- let program = db.chalk_db.checked_program().unwrap();
158
- */
159
- let mut db = MockDatabase { panic : false } ;
160
-
161
- let peeled_goal: UCanonical < InEnvironment < Goal < ChalkIr > > > = UCanonical {
188
+ // Goal:
189
+ //
190
+ // Foo: Bar
191
+ UCanonical {
162
192
canonical : Canonical {
163
193
binders : CanonicalVarKinds :: new ( & ChalkIr ) ,
164
194
value : InEnvironment {
@@ -180,17 +210,131 @@ fn unwind_safety() {
180
210
} ,
181
211
} ,
182
212
universes : 1 ,
213
+ }
214
+ }
215
+
216
+ #[ test]
217
+ fn custom_clauses_panics ( ) {
218
+ use std:: panic;
219
+
220
+ let peeled_goal = prepare_goal ( ) ;
221
+ let mut solver = SolverChoice :: slg_default ( ) . into_solver ( ) ;
222
+
223
+ // solve goal but this will panic
224
+ let mut db = MockDatabase {
225
+ panicking_method : PanickingMethod :: CustomClauses ,
226
+ } ;
227
+ let result = panic:: catch_unwind ( panic:: AssertUnwindSafe ( || {
228
+ solver. solve ( & db, & peeled_goal) ;
229
+ } ) ) ;
230
+ assert ! ( result. is_err( ) ) ;
231
+
232
+ // solve again but without panicking this time
233
+ db. panicking_method = PanickingMethod :: NoPanic ;
234
+ assert ! ( solver. solve( & db, & peeled_goal) . is_some( ) ) ;
235
+ }
236
+
237
+ #[ test]
238
+ fn trait_datum_panics ( ) {
239
+ use std:: panic;
240
+
241
+ let peeled_goal = prepare_goal ( ) ;
242
+ let mut solver = SolverChoice :: slg_default ( ) . into_solver ( ) ;
243
+
244
+ // solve goal but this will panic
245
+ let mut db = MockDatabase {
246
+ panicking_method : PanickingMethod :: TraitDatum ,
247
+ } ;
248
+ let result = panic:: catch_unwind ( panic:: AssertUnwindSafe ( || {
249
+ solver. solve ( & db, & peeled_goal) ;
250
+ } ) ) ;
251
+ assert ! ( result. is_err( ) ) ;
252
+
253
+ // solve again but without panicking this time
254
+ db. panicking_method = PanickingMethod :: NoPanic ;
255
+ assert ! ( solver. solve( & db, & peeled_goal) . is_some( ) ) ;
256
+ }
257
+
258
+ #[ test]
259
+ fn impl_datum_panics ( ) {
260
+ use std:: panic;
261
+
262
+ let peeled_goal = prepare_goal ( ) ;
263
+ let mut solver = SolverChoice :: slg_default ( ) . into_solver ( ) ;
264
+
265
+ // solve goal but this will panic
266
+ let mut db = MockDatabase {
267
+ panicking_method : PanickingMethod :: ImplDatum ,
268
+ } ;
269
+ let result = panic:: catch_unwind ( panic:: AssertUnwindSafe ( || {
270
+ solver. solve ( & db, & peeled_goal) ;
271
+ } ) ) ;
272
+ assert ! ( result. is_err( ) ) ;
273
+
274
+ // solve again but without panicking this time
275
+ db. panicking_method = PanickingMethod :: NoPanic ;
276
+ assert ! ( solver. solve( & db, & peeled_goal) . is_some( ) ) ;
277
+ }
278
+
279
+ #[ test]
280
+ fn impls_for_trait ( ) {
281
+ use std:: panic;
282
+
283
+ let peeled_goal = prepare_goal ( ) ;
284
+ let mut solver = SolverChoice :: slg_default ( ) . into_solver ( ) ;
285
+
286
+ // solve goal but this will panic
287
+ let mut db = MockDatabase {
288
+ panicking_method : PanickingMethod :: ImplsForTrait ,
289
+ } ;
290
+ let result = panic:: catch_unwind ( panic:: AssertUnwindSafe ( || {
291
+ solver. solve ( & db, & peeled_goal) ;
292
+ } ) ) ;
293
+ assert ! ( result. is_err( ) ) ;
294
+
295
+ // solve again but without panicking this time
296
+ db. panicking_method = PanickingMethod :: NoPanic ;
297
+ assert ! ( solver. solve( & db, & peeled_goal) . is_some( ) ) ;
298
+ }
299
+
300
+ #[ test]
301
+ fn program_clauses_for_env ( ) {
302
+ use std:: panic;
303
+
304
+ let peeled_goal = prepare_goal ( ) ;
305
+ let mut solver = SolverChoice :: slg_default ( ) . into_solver ( ) ;
306
+
307
+ // solve goal but this will panic
308
+ let mut db = MockDatabase {
309
+ panicking_method : PanickingMethod :: ProgramClausesForEnv ,
183
310
} ;
311
+ let result = panic:: catch_unwind ( panic:: AssertUnwindSafe ( || {
312
+ solver. solve ( & db, & peeled_goal) ;
313
+ } ) ) ;
314
+ assert ! ( result. is_err( ) ) ;
184
315
316
+ // solve again but without panicking this time
317
+ db. panicking_method = PanickingMethod :: NoPanic ;
318
+ assert ! ( solver. solve( & db, & peeled_goal) . is_some( ) ) ;
319
+ }
320
+
321
+ #[ test]
322
+ fn interner ( ) {
323
+ use std:: panic;
324
+
325
+ let peeled_goal = prepare_goal ( ) ;
185
326
let mut solver = SolverChoice :: slg_default ( ) . into_solver ( ) ;
327
+
186
328
// solve goal but this will panic
187
- db. panic = true ;
329
+ let mut db = MockDatabase {
330
+ panicking_method : PanickingMethod :: Interner ,
331
+ } ;
188
332
let result = panic:: catch_unwind ( panic:: AssertUnwindSafe ( || {
189
333
solver. solve ( & db, & peeled_goal) ;
190
334
} ) ) ;
191
335
assert ! ( result. is_err( ) ) ;
192
336
193
337
// solve again but without panicking this time
194
- db. panic = false ;
338
+ db. panicking_method = PanickingMethod :: NoPanic ;
195
339
assert ! ( solver. solve( & db, & peeled_goal) . is_some( ) ) ;
196
340
}
0 commit comments