Columns to be produced.
(
&self,
relation: &mut MirRelationExpr,
mut columns: BTreeSet<usize>,
gets: &mut BTreeMap<Id, BTreeSet<usize>>,
)
| 100 | impl Demand { |
| 101 | /// Columns to be produced. |
| 102 | fn action( |
| 103 | &self, |
| 104 | relation: &mut MirRelationExpr, |
| 105 | mut columns: BTreeSet<usize>, |
| 106 | gets: &mut BTreeMap<Id, BTreeSet<usize>>, |
| 107 | ) -> Result<(), crate::TransformError> { |
| 108 | self.checked_recur(|_| { |
| 109 | // A valid relation type is only needed for Maps, but we can't borrow |
| 110 | // the relation in the corresponding branch of the match statement, since |
| 111 | // it is already borrowed mutably. |
| 112 | let relation_type = if matches!(relation, MirRelationExpr::Map { .. }) { |
| 113 | Some(relation.typ()) |
| 114 | } else { |
| 115 | None |
| 116 | }; |
| 117 | match relation { |
| 118 | MirRelationExpr::Constant { .. } => { |
| 119 | // Nothing clever to do with constants, that I can think of. |
| 120 | Ok(()) |
| 121 | } |
| 122 | MirRelationExpr::Get { id, .. } => { |
| 123 | gets.entry(*id) |
| 124 | .or_insert_with(BTreeSet::new) |
| 125 | .extend(columns); |
| 126 | Ok(()) |
| 127 | } |
| 128 | MirRelationExpr::Let { id, value, body } => { |
| 129 | // Let harvests any requirements of get from its body, |
| 130 | // and pushes the union of the requirements at its value. |
| 131 | let id = Id::Local(*id); |
| 132 | let prior = gets.insert(id, BTreeSet::new()); |
| 133 | assert_none!(prior); // no shadowing |
| 134 | self.action(body, columns, gets)?; |
| 135 | let needs = gets.remove(&id).expect("existing gets entry"); |
| 136 | if let Some(prior) = prior { |
| 137 | gets.insert(id, prior); |
| 138 | } |
| 139 | |
| 140 | self.action(value, needs, gets) |
| 141 | } |
| 142 | MirRelationExpr::LetRec { |
| 143 | ids, |
| 144 | values, |
| 145 | limits: _, |
| 146 | body, |
| 147 | } => { |
| 148 | let ids_used_across_iterations = MirRelationExpr::recursive_ids(ids, values) |
| 149 | .iter() |
| 150 | .map(|id| Id::Local(*id)) |
| 151 | .collect::<BTreeSet<_>>(); |
| 152 | let ids = ids.iter().map(|id| Id::Local(*id)).collect_vec(); |
| 153 | for id in ids.iter() { |
| 154 | let prior = gets.insert(id.clone(), BTreeSet::new()); |
| 155 | assert_none!(prior); // no shadowing |
| 156 | } |
| 157 | self.action(body, columns, gets)?; |
| 158 | for (id, value) in ids.iter().rev().zip_eq(values.iter_mut().rev()) { |
| 159 | let needs = if !ids_used_across_iterations.contains(id) { |
no test coverage detected