From f3b3156da522f9135f58ffe453dface1489da6a7 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 6 Nov 2020 19:02:42 +0100 Subject: [PATCH] Fix "var_universe invoked on bound variable" crash This should fix rust-analyzer/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. --- chalk-solve/src/infer.rs | 9 +++++++++ tests/test/numerics.rs | 23 +++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/chalk-solve/src/infer.rs b/chalk-solve/src/infer.rs index df7fec405a6..ee151aef420 100644 --- a/chalk-solve/src/infer.rs +++ b/chalk-solve/src/infer.rs @@ -119,6 +119,15 @@ impl InferenceTable { } pub fn normalize_ty_shallow(&mut self, interner: &I, leaf: &Ty) -> Option> { + // 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) -> Option> { self.probe_var(leaf.inference_var(interner)?) .map(|p| p.assert_ty_ref(interner).clone()) } diff --git a/tests/test/numerics.rs b/tests/test/numerics.rs index 69fb0b98b76..da0953ce7e9 100644 --- a/tests/test/numerics.rs +++ b/tests/test/numerics.rs @@ -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 {} + + impl Foo for Bar<(T, T, i32, i32)> {} + } + + goal { + exists { + Bar<(N, T, T, T)>: Foo + } + } yields { + "Unique" + } + } +}