Skip to content

Commit 869ff06

Browse files
committed
Refactor LowerWhereClause for multiple domain goals
1 parent b953f83 commit 869ff06

File tree

2 files changed

+60
-18
lines changed

2 files changed

+60
-18
lines changed

src/ir/lowering/mod.rs

+37-18
Original file line numberDiff line numberDiff line change
@@ -412,26 +412,36 @@ trait LowerWhereClauseVec<T> {
412412

413413
impl LowerWhereClauseVec<ir::DomainGoal> for [WhereClause] {
414414
fn lower(&self, env: &Env) -> Result<Vec<ir::DomainGoal>> {
415-
self.iter().map(|wc| wc.lower(env)).collect()
415+
self.iter()
416+
.flat_map(|wc| match wc.lower(env) {
417+
Ok(v) => v.into_iter().map(Ok).collect(),
418+
Err(e) => vec![Err(e)],
419+
})
420+
.collect()
416421
}
417422
}
418423

419424
impl LowerWhereClauseVec<ir::QuantifiedDomainGoal> for [QuantifiedWhereClause] {
420425
fn lower(&self, env: &Env) -> Result<Vec<ir::QuantifiedDomainGoal>> {
421-
self.iter().map(|wc| wc.lower(env)).collect()
426+
self.iter()
427+
.flat_map(|wc| match wc.lower(env) {
428+
Ok(v) => v.into_iter().map(Ok).collect(),
429+
Err(e) => vec![Err(e)],
430+
})
431+
.collect()
422432
}
423433
}
424434

425435
trait LowerWhereClause<T> {
426-
fn lower(&self, env: &Env) -> Result<T>;
436+
fn lower(&self, env: &Env) -> Result<Vec<T>>;
427437
}
428438

429439
/// Lowers a where-clause in the context of a clause (i.e. in "negative"
430440
/// position); this is limited to the kinds of where-clauses users can actually
431441
/// type in Rust and well-formedness checks.
432442
impl LowerWhereClause<ir::DomainGoal> for WhereClause {
433-
fn lower(&self, env: &Env) -> Result<ir::DomainGoal> {
434-
Ok(match self {
443+
fn lower(&self, env: &Env) -> Result<Vec<ir::DomainGoal>> {
444+
let goal = match self {
435445
WhereClause::Implemented { trait_ref } => {
436446
ir::DomainGoal::Holds(ir::WhereClauseAtom::Implemented(trait_ref.lower(env)?))
437447
}
@@ -478,17 +488,18 @@ impl LowerWhereClause<ir::DomainGoal> for WhereClause {
478488
target: target.lower(env)?
479489
})
480490
}
481-
})
491+
};
492+
Ok(vec![goal])
482493
}
483494
}
484495

485496
impl LowerWhereClause<ir::QuantifiedDomainGoal> for QuantifiedWhereClause {
486-
fn lower(&self, env: &Env) -> Result<ir::QuantifiedDomainGoal> {
497+
fn lower(&self, env: &Env) -> Result<Vec<ir::QuantifiedDomainGoal>> {
487498
let parameter_kinds = self.parameter_kinds.iter().map(|pk| pk.lower());
488499
let binders = env.in_binders(parameter_kinds, |env| {
489500
Ok(self.where_clause.lower(env)?)
490501
})?;
491-
Ok(binders)
502+
Ok(binders.into_iter().collect())
492503
}
493504
}
494505

@@ -497,7 +508,7 @@ impl LowerWhereClause<ir::QuantifiedDomainGoal> for QuantifiedWhereClause {
497508
/// can appear, because it includes all the sorts of things that the compiler
498509
/// must verify.
499510
impl LowerWhereClause<ir::LeafGoal> for WhereClause {
500-
fn lower(&self, env: &Env) -> Result<ir::LeafGoal> {
511+
fn lower(&self, env: &Env) -> Result<Vec<ir::LeafGoal>> {
501512
Ok(match *self {
502513
WhereClause::Implemented { .. }
503514
| WhereClause::ProjectionEq { .. }
@@ -507,17 +518,17 @@ impl LowerWhereClause<ir::LeafGoal> for WhereClause {
507518
| WhereClause::TyFromEnv { .. }
508519
| WhereClause::TraitRefFromEnv { .. }
509520
| WhereClause::Derefs { .. } => {
510-
let g: ir::DomainGoal = self.lower(env)?;
511-
g.cast()
521+
let goals: Vec<ir::DomainGoal> = self.lower(env)?;
522+
goals.into_iter().map(|g| g.cast()).collect()
512523
}
513-
WhereClause::UnifyTys { ref a, ref b } => ir::EqGoal {
524+
WhereClause::UnifyTys { ref a, ref b } => vec![ir::EqGoal {
514525
a: ir::ParameterKind::Ty(a.lower(env)?),
515526
b: ir::ParameterKind::Ty(b.lower(env)?),
516-
}.cast(),
517-
WhereClause::UnifyLifetimes { ref a, ref b } => ir::EqGoal {
527+
}.cast()],
528+
WhereClause::UnifyLifetimes { ref a, ref b } => vec![ir::EqGoal {
518529
a: ir::ParameterKind::Lifetime(a.lower(env)?),
519530
b: ir::ParameterKind::Lifetime(b.lower(env)?),
520-
}.cast(),
531+
}.cast()],
521532
WhereClause::TraitInScope { trait_name } => {
522533
let id = match env.lookup(trait_name)? {
523534
NameLookup::Type(id) => id,
@@ -528,7 +539,7 @@ impl LowerWhereClause<ir::LeafGoal> for WhereClause {
528539
bail!(ErrorKind::NotTrait(trait_name));
529540
}
530541

531-
ir::DomainGoal::InScope(id).cast()
542+
vec![ir::DomainGoal::InScope(id).cast()]
532543
}
533544
})
534545
}
@@ -837,7 +848,10 @@ trait LowerClause {
837848
impl LowerClause for Clause {
838849
fn lower_clause(&self, env: &Env) -> Result<ir::ProgramClause> {
839850
let implication = env.in_binders(self.all_parameters(), |env| {
840-
let consequence: ir::DomainGoal = self.consequence.lower(env)?;
851+
let consequences: Vec<ir::DomainGoal> = self.consequence.lower(env)?;
852+
assert_eq!(1, consequences.len());
853+
let consequence = consequences.into_iter().next().unwrap();
854+
841855
let mut conditions: Vec<ir::Goal> = self.conditions
842856
.iter()
843857
.map(|g| g.lower(env).map(|g| *g))
@@ -976,7 +990,12 @@ impl<'k> LowerGoal<Env<'k>> for Goal {
976990
Ok(Box::new(ir::Goal::And(g1.lower(env)?, g2.lower(env)?)))
977991
}
978992
Goal::Not(g) => Ok(Box::new(ir::Goal::Not(g.lower(env)?))),
979-
Goal::Leaf(wc) => Ok(Box::new(ir::Goal::Leaf(wc.lower(env)?))),
993+
Goal::Leaf(wc) => {
994+
let leaf = wc.lower(env)?;
995+
assert_eq!(1, leaf.len());
996+
let leaf = leaf.into_iter().next().unwrap();
997+
Ok(Box::new(ir::Goal::Leaf(leaf)))
998+
}
980999
}
9811000
}
9821001
}

src/ir/mod.rs

+23
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,29 @@ impl<T> Binders<T> {
687687
}
688688
}
689689

690+
/// Allows iterating over a Binders<Vec<T>>, for instance.
691+
/// Each element will include the same set of parameter bounds.
692+
impl<V: IntoIterator> IntoIterator for Binders<V> {
693+
type Item = Binders<<V as IntoIterator>::Item>;
694+
type IntoIter = BindersIntoIterator<V>;
695+
696+
fn into_iter(self) -> Self::IntoIter {
697+
BindersIntoIterator { iter: self.value.into_iter(), binders: self.binders }
698+
}
699+
}
700+
701+
pub struct BindersIntoIterator<V: IntoIterator> {
702+
iter: <V as IntoIterator>::IntoIter,
703+
binders: Vec<ParameterKind<()>>,
704+
}
705+
706+
impl<V: IntoIterator> Iterator for BindersIntoIterator<V> {
707+
type Item = Binders<<V as IntoIterator>::Item>;
708+
fn next(&mut self) -> Option<Self::Item> {
709+
self.iter.next().map(|v| Binders { binders: self.binders.clone(), value: v })
710+
}
711+
}
712+
690713
/// Represents one clause of the form `consequence :- conditions` where
691714
/// `conditions = cond_1 && cond_2 && ...` is the conjunction of the individual
692715
/// conditions.

0 commit comments

Comments
 (0)