(mut bases: Vec<Vec<PyTypeRef>>)
| 2792 | } |
| 2793 | |
| 2794 | fn linearise_mro(mut bases: Vec<Vec<PyTypeRef>>) -> Result<Vec<PyTypeRef>, String> { |
| 2795 | vm_trace!("Linearise MRO: {:?}", bases); |
| 2796 | // Python requires that the class direct bases are kept in the same order. |
| 2797 | // This is called local precedence ordering. |
| 2798 | // This means we must verify that for classes A(), B(A) we must reject C(A, B) even though this |
| 2799 | // algorithm will allow the mro ordering of [C, B, A, object]. |
| 2800 | // To verify this, we make sure non of the direct bases are in the mro of bases after them. |
| 2801 | for (i, base_mro) in bases.iter().enumerate() { |
| 2802 | let base = &base_mro[0]; // MROs cannot be empty. |
| 2803 | for later_mro in &bases[i + 1..] { |
| 2804 | // We start at index 1 to skip direct bases. |
| 2805 | // This will not catch duplicate bases, but such a thing is already tested for. |
| 2806 | if later_mro[1..].iter().any(|cls| cls.is(base)) { |
| 2807 | return Err(format!( |
| 2808 | "Cannot create a consistent method resolution order (MRO) for bases {}", |
| 2809 | bases.iter().map(|x| x.first().unwrap()).format(", ") |
| 2810 | )); |
| 2811 | } |
| 2812 | } |
| 2813 | } |
| 2814 | |
| 2815 | let mut result = vec![]; |
| 2816 | while !bases.is_empty() { |
| 2817 | let head = take_next_base(&mut bases).ok_or_else(|| { |
| 2818 | // Take the head class of each class here. Now that we have reached the problematic bases. |
| 2819 | // Because this failed, we assume the lists cannot be empty. |
| 2820 | format!( |
| 2821 | "Cannot create a consistent method resolution order (MRO) for bases {}", |
| 2822 | bases.iter().map(|x| x.first().unwrap()).format(", ") |
| 2823 | ) |
| 2824 | })?; |
| 2825 | |
| 2826 | result.push(head); |
| 2827 | |
| 2828 | bases.retain(|x| !x.is_empty()); |
| 2829 | } |
| 2830 | Ok(result) |
| 2831 | } |
| 2832 | |
| 2833 | fn calculate_meta_class( |
| 2834 | metatype: PyTypeRef, |
no test coverage detected