Auto merge of #18139 - ShoyuVanilla:issue-18109, r=Veykril
fix: Extend `type_variable_table` when modifying index is larger than the table size Fixes #18109 Whenever we create an inference variable in r-a, we extend `type_variable_table` to matching size here;f4aca78c92/crates/hir-ty/src/infer/unify.rs (L378-L381)
But sometimes, an inference variable is [created from chalk](ab710e0c9b/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;f4aca78c92/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
This commit is contained in:
commit
627ccda3e5
@ -266,14 +266,16 @@ pub(super) fn propagate_diverging_flag(&mut self) {
|
|||||||
}
|
}
|
||||||
let v = InferenceVar::from(i as u32);
|
let v = InferenceVar::from(i as u32);
|
||||||
let root = self.var_unification_table.inference_var_root(v);
|
let root = self.var_unification_table.inference_var_root(v);
|
||||||
if let Some(data) = self.type_variable_table.get_mut(root.index() as usize) {
|
self.modify_type_variable_flag(root, |f| {
|
||||||
*data |= TypeVariableFlags::DIVERGING;
|
*f |= TypeVariableFlags::DIVERGING;
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) {
|
pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) {
|
||||||
self.type_variable_table[iv.index() as usize].set(TypeVariableFlags::DIVERGING, diverging);
|
self.modify_type_variable_flag(iv, |f| {
|
||||||
|
f.set(TypeVariableFlags::DIVERGING, diverging);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
|
fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
|
||||||
@ -370,6 +372,18 @@ pub(crate) fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
|
|||||||
var
|
var
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn modify_type_variable_flag<F>(&mut self, var: InferenceVar, cb: F)
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut TypeVariableFlags),
|
||||||
|
{
|
||||||
|
let idx = var.index() as usize;
|
||||||
|
if self.type_variable_table.len() <= idx {
|
||||||
|
self.extend_type_variable_table(idx);
|
||||||
|
}
|
||||||
|
if let Some(f) = self.type_variable_table.get_mut(idx) {
|
||||||
|
cb(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
fn extend_type_variable_table(&mut self, to_index: usize) {
|
fn extend_type_variable_table(&mut self, to_index: usize) {
|
||||||
let count = to_index - self.type_variable_table.len() + 1;
|
let count = to_index - self.type_variable_table.len() + 1;
|
||||||
self.type_variable_table.extend(iter::repeat(TypeVariableFlags::default()).take(count));
|
self.type_variable_table.extend(iter::repeat(TypeVariableFlags::default()).take(count));
|
||||||
|
@ -2232,3 +2232,66 @@ async fn f<A, B, C>() -> Bar {}
|
|||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_18109() {
|
||||||
|
check_infer(
|
||||||
|
r#"
|
||||||
|
//- minicore: option
|
||||||
|
struct Map<T, U>(T, U);
|
||||||
|
|
||||||
|
impl<T, U> Map<T, U> {
|
||||||
|
fn new() -> Self { loop {} }
|
||||||
|
fn get(&self, _: &T) -> Option<&U> { loop {} }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test(x: bool) {
|
||||||
|
let map = Map::new();
|
||||||
|
let _ = match x {
|
||||||
|
true => {
|
||||||
|
let Some(val) = map.get(&8) else { return };
|
||||||
|
*val
|
||||||
|
}
|
||||||
|
false => return,
|
||||||
|
_ => 42,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
69..80 '{ loop {} }': Map<T, U>
|
||||||
|
71..78 'loop {}': !
|
||||||
|
76..78 '{}': ()
|
||||||
|
93..97 'self': &'? Map<T, U>
|
||||||
|
99..100 '_': &'? T
|
||||||
|
120..131 '{ loop {} }': Option<&'? U>
|
||||||
|
122..129 'loop {}': !
|
||||||
|
127..129 '{}': ()
|
||||||
|
143..144 'x': bool
|
||||||
|
152..354 '{ ... }; }': ()
|
||||||
|
162..165 'map': Map<i32, i32>
|
||||||
|
168..176 'Map::new': fn new<i32, i32>() -> Map<i32, i32>
|
||||||
|
168..178 'Map::new()': Map<i32, i32>
|
||||||
|
188..189 '_': i32
|
||||||
|
192..351 'match ... }': i32
|
||||||
|
198..199 'x': bool
|
||||||
|
210..214 'true': bool
|
||||||
|
210..214 'true': bool
|
||||||
|
218..303 '{ ... }': i32
|
||||||
|
236..245 'Some(val)': Option<&'? i32>
|
||||||
|
241..244 'val': &'? i32
|
||||||
|
248..251 'map': Map<i32, i32>
|
||||||
|
248..259 'map.get(&8)': Option<&'? i32>
|
||||||
|
256..258 '&8': &'? i32
|
||||||
|
257..258 '8': i32
|
||||||
|
265..275 '{ return }': !
|
||||||
|
267..273 'return': !
|
||||||
|
289..293 '*val': i32
|
||||||
|
290..293 'val': &'? i32
|
||||||
|
312..317 'false': bool
|
||||||
|
312..317 'false': bool
|
||||||
|
321..327 'return': !
|
||||||
|
337..338 '_': bool
|
||||||
|
342..344 '42': i32
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user