]> git.lizzy.rs Git - rust.git/blob - src/librustc_data_structures/obligation_forest/tests.rs
Rollup merge of #64874 - matthewjasper:simplify-euv, r=eddyb
[rust.git] / src / librustc_data_structures / obligation_forest / tests.rs
1 use super::*;
2
3 use std::fmt;
4 use std::marker::PhantomData;
5
6 impl<'a> super::ForestObligation for &'a str {
7     type Predicate = &'a str;
8
9     fn as_predicate(&self) -> &Self::Predicate {
10         self
11     }
12 }
13
14 struct ClosureObligationProcessor<OF, BF, O, E> {
15     process_obligation: OF,
16     _process_backedge: BF,
17     marker: PhantomData<(O, E)>,
18 }
19
20 #[allow(non_snake_case)]
21 fn C<OF, BF, O>(of: OF, bf: BF) -> ClosureObligationProcessor<OF, BF, O, &'static str>
22     where OF: FnMut(&mut O) -> ProcessResult<O, &'static str>,
23           BF: FnMut(&[O])
24 {
25     ClosureObligationProcessor {
26         process_obligation: of,
27         _process_backedge: bf,
28         marker: PhantomData
29     }
30 }
31
32 impl<OF, BF, O, E> ObligationProcessor for ClosureObligationProcessor<OF, BF, O, E>
33     where O: super::ForestObligation + fmt::Debug,
34           E: fmt::Debug,
35           OF: FnMut(&mut O) -> ProcessResult<O, E>,
36           BF: FnMut(&[O])
37 {
38     type Obligation = O;
39     type Error = E;
40
41     fn process_obligation(&mut self,
42                           obligation: &mut Self::Obligation)
43                           -> ProcessResult<Self::Obligation, Self::Error>
44     {
45         (self.process_obligation)(obligation)
46     }
47
48     fn process_backedge<'c, I>(&mut self, _cycle: I,
49                                _marker: PhantomData<&'c Self::Obligation>)
50         where I: Clone + Iterator<Item=&'c Self::Obligation>
51     {
52     }
53 }
54
55
56 #[test]
57 fn push_pop() {
58     let mut forest = ObligationForest::new();
59     forest.register_obligation("A");
60     forest.register_obligation("B");
61     forest.register_obligation("C");
62
63     // first round, B errors out, A has subtasks, and C completes, creating this:
64     //      A |-> A.1
65     //        |-> A.2
66     //        |-> A.3
67     let Outcome { completed: ok, errors: err, .. } =
68         forest.process_obligations(&mut C(|obligation| {
69             match *obligation {
70                 "A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]),
71                 "B" => ProcessResult::Error("B is for broken"),
72                 "C" => ProcessResult::Changed(vec![]),
73                 _ => unreachable!(),
74             }
75         }, |_| {}), DoCompleted::Yes);
76     assert_eq!(ok.unwrap(), vec!["C"]);
77     assert_eq!(err,
78                vec![Error {
79                         error: "B is for broken",
80                         backtrace: vec!["B"],
81                     }]);
82
83     // second round: two delays, one success, creating an uneven set of subtasks:
84     //      A |-> A.1
85     //        |-> A.2
86     //        |-> A.3 |-> A.3.i
87     //      D |-> D.1
88     //        |-> D.2
89     forest.register_obligation("D");
90     let Outcome { completed: ok, errors: err, .. } =
91         forest.process_obligations(&mut C(|obligation| {
92             match *obligation {
93                 "A.1" => ProcessResult::Unchanged,
94                 "A.2" => ProcessResult::Unchanged,
95                 "A.3" => ProcessResult::Changed(vec!["A.3.i"]),
96                 "D" => ProcessResult::Changed(vec!["D.1", "D.2"]),
97                 _ => unreachable!(),
98             }
99         }, |_| {}), DoCompleted::Yes);
100     assert_eq!(ok.unwrap(), Vec::<&'static str>::new());
101     assert_eq!(err, Vec::new());
102
103
104     // third round: ok in A.1 but trigger an error in A.2. Check that it
105     // propagates to A, but not D.1 or D.2.
106     //      D |-> D.1 |-> D.1.i
107     //        |-> D.2 |-> D.2.i
108     let Outcome { completed: ok, errors: err, .. } =
109         forest.process_obligations(&mut C(|obligation| {
110             match *obligation {
111                 "A.1" => ProcessResult::Changed(vec![]),
112                 "A.2" => ProcessResult::Error("A is for apple"),
113                 "A.3.i" => ProcessResult::Changed(vec![]),
114                 "D.1" => ProcessResult::Changed(vec!["D.1.i"]),
115                 "D.2" => ProcessResult::Changed(vec!["D.2.i"]),
116                 _ => unreachable!(),
117             }
118         }, |_| {}), DoCompleted::Yes);
119     let mut ok = ok.unwrap();
120     ok.sort();
121     assert_eq!(ok, vec!["A.1", "A.3", "A.3.i"]);
122     assert_eq!(err,
123                vec![Error {
124                         error: "A is for apple",
125                         backtrace: vec!["A.2", "A"],
126                     }]);
127
128     // fourth round: error in D.1.i
129     let Outcome { completed: ok, errors: err, .. } =
130         forest.process_obligations(&mut C(|obligation| {
131             match *obligation {
132                 "D.1.i" => ProcessResult::Error("D is for dumb"),
133                 "D.2.i" => ProcessResult::Changed(vec![]),
134                 _ => panic!("unexpected obligation {:?}", obligation),
135             }
136         }, |_| {}), DoCompleted::Yes);
137     let mut ok = ok.unwrap();
138     ok.sort();
139     assert_eq!(ok, vec!["D.2", "D.2.i"]);
140     assert_eq!(err,
141                vec![Error {
142                         error: "D is for dumb",
143                         backtrace: vec!["D.1.i", "D.1", "D"],
144                     }]);
145 }
146
147 // Test that if a tree with grandchildren succeeds, everything is
148 // reported as expected:
149 // A
150 //   A.1
151 //   A.2
152 //      A.2.i
153 //      A.2.ii
154 //   A.3
155 #[test]
156 fn success_in_grandchildren() {
157     let mut forest = ObligationForest::new();
158     forest.register_obligation("A");
159
160     let Outcome { completed: ok, errors: err, .. } =
161         forest.process_obligations(&mut C(|obligation| {
162             match *obligation {
163                 "A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]),
164                 _ => unreachable!(),
165             }
166         }, |_| {}), DoCompleted::Yes);
167     assert!(ok.unwrap().is_empty());
168     assert!(err.is_empty());
169
170     let Outcome { completed: ok, errors: err, .. } =
171         forest.process_obligations(&mut C(|obligation| {
172             match *obligation {
173                 "A.1" => ProcessResult::Changed(vec![]),
174                 "A.2" => ProcessResult::Changed(vec!["A.2.i", "A.2.ii"]),
175                 "A.3" => ProcessResult::Changed(vec![]),
176                 _ => unreachable!(),
177             }
178         }, |_| {}), DoCompleted::Yes);
179     let mut ok = ok.unwrap();
180     ok.sort();
181     assert_eq!(ok, vec!["A.1", "A.3"]);
182     assert!(err.is_empty());
183
184     let Outcome { completed: ok, errors: err, .. } =
185         forest.process_obligations(&mut C(|obligation| {
186             match *obligation {
187                 "A.2.i" => ProcessResult::Changed(vec!["A.2.i.a"]),
188                 "A.2.ii" => ProcessResult::Changed(vec![]),
189                 _ => unreachable!(),
190             }
191         }, |_| {}), DoCompleted::Yes);
192     assert_eq!(ok.unwrap(), vec!["A.2.ii"]);
193     assert!(err.is_empty());
194
195     let Outcome { completed: ok, errors: err, .. } =
196         forest.process_obligations(&mut C(|obligation| {
197             match *obligation {
198                 "A.2.i.a" => ProcessResult::Changed(vec![]),
199                 _ => unreachable!(),
200             }
201         }, |_| {}), DoCompleted::Yes);
202     let mut ok = ok.unwrap();
203     ok.sort();
204     assert_eq!(ok, vec!["A", "A.2", "A.2.i", "A.2.i.a"]);
205     assert!(err.is_empty());
206
207     let Outcome { completed: ok, errors: err, .. } =
208         forest.process_obligations(&mut C(|_| unreachable!(), |_| {}),
209         DoCompleted::Yes);
210
211     assert!(ok.unwrap().is_empty());
212     assert!(err.is_empty());
213 }
214
215 #[test]
216 fn to_errors_no_throw() {
217     // check that converting multiple children with common parent (A)
218     // yields to correct errors (and does not panic, in particular).
219     let mut forest = ObligationForest::new();
220     forest.register_obligation("A");
221     let Outcome { completed: ok, errors: err, .. } =
222         forest.process_obligations(&mut C(|obligation| {
223             match *obligation {
224                 "A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]),
225                 _ => unreachable!(),
226             }
227         }, |_|{}), DoCompleted::Yes);
228     assert_eq!(ok.unwrap().len(), 0);
229     assert_eq!(err.len(), 0);
230     let errors = forest.to_errors(());
231     assert_eq!(errors[0].backtrace, vec!["A.1", "A"]);
232     assert_eq!(errors[1].backtrace, vec!["A.2", "A"]);
233     assert_eq!(errors[2].backtrace, vec!["A.3", "A"]);
234     assert_eq!(errors.len(), 3);
235 }
236
237 #[test]
238 fn diamond() {
239     // check that diamond dependencies are handled correctly
240     let mut forest = ObligationForest::new();
241     forest.register_obligation("A");
242     let Outcome { completed: ok, errors: err, .. } =
243         forest.process_obligations(&mut C(|obligation| {
244             match *obligation {
245                 "A" => ProcessResult::Changed(vec!["A.1", "A.2"]),
246                 _ => unreachable!(),
247             }
248         }, |_|{}), DoCompleted::Yes);
249     assert_eq!(ok.unwrap().len(), 0);
250     assert_eq!(err.len(), 0);
251
252     let Outcome { completed: ok, errors: err, .. } =
253         forest.process_obligations(&mut C(|obligation| {
254             match *obligation {
255                 "A.1" => ProcessResult::Changed(vec!["D"]),
256                 "A.2" => ProcessResult::Changed(vec!["D"]),
257                 _ => unreachable!(),
258             }
259         }, |_|{}), DoCompleted::Yes);
260     assert_eq!(ok.unwrap().len(), 0);
261     assert_eq!(err.len(), 0);
262
263     let mut d_count = 0;
264     let Outcome { completed: ok, errors: err, .. } =
265         forest.process_obligations(&mut C(|obligation| {
266             match *obligation {
267                 "D" => { d_count += 1; ProcessResult::Changed(vec![]) },
268                 _ => unreachable!(),
269             }
270         }, |_|{}), DoCompleted::Yes);
271     assert_eq!(d_count, 1);
272     let mut ok = ok.unwrap();
273     ok.sort();
274     assert_eq!(ok, vec!["A", "A.1", "A.2", "D"]);
275     assert_eq!(err.len(), 0);
276
277     let errors = forest.to_errors(());
278     assert_eq!(errors.len(), 0);
279
280     forest.register_obligation("A'");
281     let Outcome { completed: ok, errors: err, .. } =
282         forest.process_obligations(&mut C(|obligation| {
283             match *obligation {
284                 "A'" => ProcessResult::Changed(vec!["A'.1", "A'.2"]),
285                 _ => unreachable!(),
286             }
287         }, |_|{}), DoCompleted::Yes);
288     assert_eq!(ok.unwrap().len(), 0);
289     assert_eq!(err.len(), 0);
290
291     let Outcome { completed: ok, errors: err, .. } =
292         forest.process_obligations(&mut C(|obligation| {
293             match *obligation {
294                 "A'.1" => ProcessResult::Changed(vec!["D'", "A'"]),
295                 "A'.2" => ProcessResult::Changed(vec!["D'"]),
296                 _ => unreachable!(),
297             }
298         }, |_|{}), DoCompleted::Yes);
299     assert_eq!(ok.unwrap().len(), 0);
300     assert_eq!(err.len(), 0);
301
302     let mut d_count = 0;
303     let Outcome { completed: ok, errors: err, .. } =
304         forest.process_obligations(&mut C(|obligation| {
305             match *obligation {
306                 "D'" => { d_count += 1; ProcessResult::Error("operation failed") },
307                 _ => unreachable!(),
308             }
309         }, |_|{}), DoCompleted::Yes);
310     assert_eq!(d_count, 1);
311     assert_eq!(ok.unwrap().len(), 0);
312     assert_eq!(err, vec![super::Error {
313         error: "operation failed",
314         backtrace: vec!["D'", "A'.1", "A'"]
315     }]);
316
317     let errors = forest.to_errors(());
318     assert_eq!(errors.len(), 0);
319 }
320
321 #[test]
322 fn done_dependency() {
323     // check that the local cache works
324     let mut forest = ObligationForest::new();
325     forest.register_obligation("A: Sized");
326     forest.register_obligation("B: Sized");
327     forest.register_obligation("C: Sized");
328
329     let Outcome { completed: ok, errors: err, .. } =
330         forest.process_obligations(&mut C(|obligation| {
331             match *obligation {
332                 "A: Sized" | "B: Sized" | "C: Sized" => ProcessResult::Changed(vec![]),
333                 _ => unreachable!(),
334             }
335         }, |_|{}), DoCompleted::Yes);
336     let mut ok = ok.unwrap();
337     ok.sort();
338     assert_eq!(ok, vec!["A: Sized", "B: Sized", "C: Sized"]);
339     assert_eq!(err.len(), 0);
340
341     forest.register_obligation("(A,B,C): Sized");
342     let Outcome { completed: ok, errors: err, .. } =
343         forest.process_obligations(&mut C(|obligation| {
344             match *obligation {
345                 "(A,B,C): Sized" => ProcessResult::Changed(vec![
346                     "A: Sized",
347                     "B: Sized",
348                     "C: Sized"
349                         ]),
350                 _ => unreachable!(),
351             }
352         }, |_|{}), DoCompleted::Yes);
353     assert_eq!(ok.unwrap(), vec!["(A,B,C): Sized"]);
354     assert_eq!(err.len(), 0);
355 }
356
357 #[test]
358 fn orphan() {
359     // check that orphaned nodes are handled correctly
360     let mut forest = ObligationForest::new();
361     forest.register_obligation("A");
362     forest.register_obligation("B");
363     forest.register_obligation("C1");
364     forest.register_obligation("C2");
365
366     let Outcome { completed: ok, errors: err, .. } =
367         forest.process_obligations(&mut C(|obligation| {
368             match *obligation {
369                 "A" => ProcessResult::Changed(vec!["D", "E"]),
370                 "B" => ProcessResult::Unchanged,
371                 "C1" => ProcessResult::Changed(vec![]),
372                 "C2" => ProcessResult::Changed(vec![]),
373                 _ => unreachable!(),
374             }
375         }, |_|{}), DoCompleted::Yes);
376     let mut ok = ok.unwrap();
377     ok.sort();
378     assert_eq!(ok, vec!["C1", "C2"]);
379     assert_eq!(err.len(), 0);
380
381     let Outcome { completed: ok, errors: err, .. } =
382         forest.process_obligations(&mut C(|obligation| {
383             match *obligation {
384                 "D" | "E" => ProcessResult::Unchanged,
385                 "B" => ProcessResult::Changed(vec!["D"]),
386                 _ => unreachable!(),
387             }
388         }, |_|{}), DoCompleted::Yes);
389     assert_eq!(ok.unwrap().len(), 0);
390     assert_eq!(err.len(), 0);
391
392     let Outcome { completed: ok, errors: err, .. } =
393         forest.process_obligations(&mut C(|obligation| {
394             match *obligation {
395                 "D" => ProcessResult::Unchanged,
396                 "E" => ProcessResult::Error("E is for error"),
397                 _ => unreachable!(),
398             }
399         }, |_|{}), DoCompleted::Yes);
400     assert_eq!(ok.unwrap().len(), 0);
401     assert_eq!(err, vec![super::Error {
402         error: "E is for error",
403         backtrace: vec!["E", "A"]
404     }]);
405
406     let Outcome { completed: ok, errors: err, .. } =
407         forest.process_obligations(&mut C(|obligation| {
408             match *obligation {
409                 "D" => ProcessResult::Error("D is dead"),
410                 _ => unreachable!(),
411             }
412         }, |_|{}), DoCompleted::Yes);
413     assert_eq!(ok.unwrap().len(), 0);
414     assert_eq!(err, vec![super::Error {
415         error: "D is dead",
416         backtrace: vec!["D"]
417     }]);
418
419     let errors = forest.to_errors(());
420     assert_eq!(errors.len(), 0);
421 }
422
423 #[test]
424 fn simultaneous_register_and_error() {
425     // check that registering a failed obligation works correctly
426     let mut forest = ObligationForest::new();
427     forest.register_obligation("A");
428     forest.register_obligation("B");
429
430     let Outcome { completed: ok, errors: err, .. } =
431         forest.process_obligations(&mut C(|obligation| {
432             match *obligation {
433                 "A" => ProcessResult::Error("An error"),
434                 "B" => ProcessResult::Changed(vec!["A"]),
435                 _ => unreachable!(),
436             }
437         }, |_|{}), DoCompleted::Yes);
438     assert_eq!(ok.unwrap().len(), 0);
439     assert_eq!(err, vec![super::Error {
440         error: "An error",
441         backtrace: vec!["A"]
442     }]);
443
444     let mut forest = ObligationForest::new();
445     forest.register_obligation("B");
446     forest.register_obligation("A");
447
448     let Outcome { completed: ok, errors: err, .. } =
449         forest.process_obligations(&mut C(|obligation| {
450             match *obligation {
451                 "A" => ProcessResult::Error("An error"),
452                 "B" => ProcessResult::Changed(vec!["A"]),
453                 _ => unreachable!(),
454             }
455         }, |_|{}), DoCompleted::Yes);
456     assert_eq!(ok.unwrap().len(), 0);
457     assert_eq!(err, vec![super::Error {
458         error: "An error",
459         backtrace: vec!["A"]
460     }]);
461 }