Skip to content

Commit

Permalink
Auto merge of #649 - flodiebold:general-vars-containing-integer-vars,…
Browse files Browse the repository at this point in the history
… r=jackh726

Fix "var_universe invoked on bound variable" crash

This should fix rust-lang/rust-analyzer#5495.

`unify_ty_ty` calls `normalize_ty_shallow` on both types and then assumes that they can't be bound variables. With integer type variables, this assumption was broken, because you could have a general type variable resolving to an integer type variable resolving to i32. To fix this, `normalize_ty_shallow` probes twice, to make sure to fully resolve the variable.
  • Loading branch information
bors committed Nov 8, 2020
2 parents 4c98d7b + f3b3156 commit d112f2e
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
9 changes: 9 additions & 0 deletions chalk-solve/src/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,15 @@ impl<I: Interner> InferenceTable<I> {
}

pub fn normalize_ty_shallow(&mut self, interner: &I, leaf: &Ty<I>) -> Option<Ty<I>> {
// An integer/float type variable will never normalize to another
// variable; but a general type variable might normalize to an
// integer/float variable. So we potentially need to normalize twice to
// get at the actual value.
self.normalize_ty_shallow_inner(interner, leaf)
.map(|ty| self.normalize_ty_shallow_inner(interner, &ty).unwrap_or(ty))
}

fn normalize_ty_shallow_inner(&mut self, interner: &I, leaf: &Ty<I>) -> Option<Ty<I>> {
self.probe_var(leaf.inference_var(interner)?)
.map(|p| p.assert_ty_ref(interner).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 @@ -271,3 +271,26 @@ fn shl_ice() {
}
}
}

/// Regression test for rust-analyzer#5495 ("var_universe invoked on bound
/// variable" crash).
#[test]
fn unify_general_then_specific_ty() {
test! {
program {
#[non_enumerable]
trait Foo {}
struct Bar<T> {}

impl<T> Foo for Bar<(T, T, i32, i32)> {}
}

goal {
exists<T, int N> {
Bar<(N, T, T, T)>: Foo
}
} yields {
"Unique"
}
}
}

0 comments on commit d112f2e

Please sign in to comment.