Skip to content

Commit

Permalink
Auto merge of #640 - matthewjasper:anti-canonical, r=jackh726
Browse files Browse the repository at this point in the history
Replace bound lifetime variables with inference variables in AntiUnifier

This fixes an issue that caused an ICE in rust-lang/rust#78502

r? `@jackh726`
  • Loading branch information
bors committed Oct 29, 2020
2 parents 70e77f1 + 08ad8fd commit a76946b
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 1 deletion.
13 changes: 12 additions & 1 deletion chalk-engine/src/slg/aggregate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ fn is_trivial<I: Interner>(interner: &I, subst: &Canonical<Substitution<I>>) ->
/// example `Vec<u32>` anti-unified with `Vec<i32>` might be
/// `Vec<?X>`. This is a **very simplistic** anti-unifier.
///
/// NOTE: The values here are canonicalized, but output is not, this means
/// that any escaping bound variables that we see have to be replaced with
/// inference variables.
///
/// [Anti-unification]: https://en.wikipedia.org/wiki/Anti-unification_(computer_science)
struct AntiUnifier<'infer, 'intern, I: Interner> {
infer: &'infer mut InferenceTable<I>,
Expand All @@ -243,6 +247,8 @@ impl<I: Interner> AntiUnifier<'_, '_, I> {
// &'a u32)` and `for<'a, 'b> fn(&'a u32, &'b u32)` seems
// kinda hard. Don't try to be smart for now, just plop a
// variable in there and be done with it.
// This also ensures that any bound variables we do see
// were bound by `Canonical`.
(TyKind::BoundVar(_), TyKind::BoundVar(_))
| (TyKind::Function(_), TyKind::Function(_))
| (TyKind::Dyn(_), TyKind::Dyn(_)) => self.new_ty_variable(),
Expand Down Expand Up @@ -485,7 +491,12 @@ impl<I: Interner> AntiUnifier<'_, '_, I> {
fn aggregate_lifetimes(&mut self, l1: &Lifetime<I>, l2: &Lifetime<I>) -> Lifetime<I> {
let interner = self.interner;
match (l1.data(interner), l2.data(interner)) {
(LifetimeData::Phantom(..), _) | (_, LifetimeData::Phantom(..)) => unreachable!(),
(LifetimeData::Phantom(void, ..), _) | (_, LifetimeData::Phantom(void, ..)) => {
match *void {}
}
(LifetimeData::BoundVar(..), _) | (_, LifetimeData::BoundVar(..)) => {
self.new_lifetime_variable()
}
_ => {
if l1 == l2 {
l1.clone()
Expand Down
23 changes: 23 additions & 0 deletions tests/test/numerics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,3 +248,26 @@ fn ambiguous_add() {
}
}
}

/// Simplified version of a goal that needs to be solved for type checking
/// `1 << &2`.
#[test]
fn shl_ice() {
test! {
program {
//#[non_enumerable]
trait Shl<Rhs> { }

impl<'a> Shl<&'a u32> for u32 { }
impl<'a> Shl<&'a u16> for u32 { }
}

goal {
exists<U> {
u32: Shl<U>
}
} yields {
"Ambiguous"
}
}
}

0 comments on commit a76946b

Please sign in to comment.