Skip to content

Commit 627ccda

Browse files
committed
Auto merge of rust-lang#18139 - ShoyuVanilla:issue-18109, r=Veykril
fix: Extend `type_variable_table` when modifying index is larger than the table size Fixes rust-lang#18109 Whenever we create an inference variable in r-a, we extend `type_variable_table` to matching size here; https://github.com/rust-lang/rust-analyzer/blob/f4aca78c92e03354327c8f6c7fefaef9f45ab166/crates/hir-ty/src/infer/unify.rs#L378-L381 But sometimes, an inference variable is [created from chalk](https://github.com/rust-lang/chalk/blob/ab710e0c9b455403b138ef72a2fb90967a58eff3/chalk-solve/src/infer/unify.rs#L743) and passed to r-a as a type of an expression or a pattern. If r-a set diverging flag to this before the table is extended to a sufficient size, it panics here; https://github.com/rust-lang/rust-analyzer/blob/f4aca78c92e03354327c8f6c7fefaef9f45ab166/crates/hir-ty/src/infer/unify.rs#L275-L277 I think that extending table when setting diverging flag is reasonable becase we are already doing such extending to a size that covers the inference vars created from chalk and this change only covers the order-dependent random cases that this might fail
2 parents ee38991 + 59e3008 commit 627ccda

File tree

2 files changed

+81
-4
lines changed

2 files changed

+81
-4
lines changed

src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,14 +266,16 @@ impl<'a> InferenceTable<'a> {
266266
}
267267
let v = InferenceVar::from(i as u32);
268268
let root = self.var_unification_table.inference_var_root(v);
269-
if let Some(data) = self.type_variable_table.get_mut(root.index() as usize) {
270-
*data |= TypeVariableFlags::DIVERGING;
271-
}
269+
self.modify_type_variable_flag(root, |f| {
270+
*f |= TypeVariableFlags::DIVERGING;
271+
});
272272
}
273273
}
274274

275275
pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) {
276-
self.type_variable_table[iv.index() as usize].set(TypeVariableFlags::DIVERGING, diverging);
276+
self.modify_type_variable_flag(iv, |f| {
277+
f.set(TypeVariableFlags::DIVERGING, diverging);
278+
});
277279
}
278280

279281
fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
@@ -370,6 +372,18 @@ impl<'a> InferenceTable<'a> {
370372
var
371373
}
372374

375+
fn modify_type_variable_flag<F>(&mut self, var: InferenceVar, cb: F)
376+
where
377+
F: FnOnce(&mut TypeVariableFlags),
378+
{
379+
let idx = var.index() as usize;
380+
if self.type_variable_table.len() <= idx {
381+
self.extend_type_variable_table(idx);
382+
}
383+
if let Some(f) = self.type_variable_table.get_mut(idx) {
384+
cb(f);
385+
}
386+
}
373387
fn extend_type_variable_table(&mut self, to_index: usize) {
374388
let count = to_index - self.type_variable_table.len() + 1;
375389
self.type_variable_table.extend(iter::repeat(TypeVariableFlags::default()).take(count));

src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2232,3 +2232,66 @@ async fn f<A, B, C>() -> Bar {}
22322232
"#]],
22332233
);
22342234
}
2235+
2236+
#[test]
2237+
fn issue_18109() {
2238+
check_infer(
2239+
r#"
2240+
//- minicore: option
2241+
struct Map<T, U>(T, U);
2242+
2243+
impl<T, U> Map<T, U> {
2244+
fn new() -> Self { loop {} }
2245+
fn get(&self, _: &T) -> Option<&U> { loop {} }
2246+
}
2247+
2248+
fn test(x: bool) {
2249+
let map = Map::new();
2250+
let _ = match x {
2251+
true => {
2252+
let Some(val) = map.get(&8) else { return };
2253+
*val
2254+
}
2255+
false => return,
2256+
_ => 42,
2257+
};
2258+
}
2259+
"#,
2260+
expect![[r#"
2261+
69..80 '{ loop {} }': Map<T, U>
2262+
71..78 'loop {}': !
2263+
76..78 '{}': ()
2264+
93..97 'self': &'? Map<T, U>
2265+
99..100 '_': &'? T
2266+
120..131 '{ loop {} }': Option<&'? U>
2267+
122..129 'loop {}': !
2268+
127..129 '{}': ()
2269+
143..144 'x': bool
2270+
152..354 '{ ... }; }': ()
2271+
162..165 'map': Map<i32, i32>
2272+
168..176 'Map::new': fn new<i32, i32>() -> Map<i32, i32>
2273+
168..178 'Map::new()': Map<i32, i32>
2274+
188..189 '_': i32
2275+
192..351 'match ... }': i32
2276+
198..199 'x': bool
2277+
210..214 'true': bool
2278+
210..214 'true': bool
2279+
218..303 '{ ... }': i32
2280+
236..245 'Some(val)': Option<&'? i32>
2281+
241..244 'val': &'? i32
2282+
248..251 'map': Map<i32, i32>
2283+
248..259 'map.get(&8)': Option<&'? i32>
2284+
256..258 '&8': &'? i32
2285+
257..258 '8': i32
2286+
265..275 '{ return }': !
2287+
267..273 'return': !
2288+
289..293 '*val': i32
2289+
290..293 'val': &'? i32
2290+
312..317 'false': bool
2291+
312..317 'false': bool
2292+
321..327 'return': !
2293+
337..338 '_': bool
2294+
342..344 '42': i32
2295+
"#]],
2296+
);
2297+
}

0 commit comments

Comments
 (0)