Skip to content

Commit c3349bb

Browse files
committed
Rust: Add type inference example with cycle blowup
1 parent 9aebc58 commit c3349bb

File tree

2 files changed

+430
-0
lines changed

2 files changed

+430
-0
lines changed

rust/ql/test/library-tests/type-inference/dereference.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,46 @@ fn implicit_dereference() {
9393
let _y = x.is_positive(); // $ MISSING: target=is_positive type=_y:bool
9494
}
9595

96+
mod implicit_deref_coercion_cycle {
97+
use std::collections::HashMap;
98+
99+
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
100+
pub struct Key {}
101+
102+
// This example can trigger a cycle in type inference due to an implicit
103+
// dereference if we are not careful and accurate enough.
104+
//
105+
// To explain how a cycle might happen, we let `[V]` denote the type of the
106+
// type parameter `V` of `key_to_key` (i.e., the type of the values in the
107+
// map) and `[key]` denote the type of `key`.
108+
//
109+
// 1. From the first two lines we infer `[V] = &Key` and `[key] = &Key`
110+
// 2. At the 3. line we infer the type of `ref_key` to be `&[V]`.
111+
// 3. At the 4. line we impose the equality `[key] = &[V]`, not accounting
112+
// for the implicit deref caused by a coercion.
113+
// 4. At the last line we infer `[key] = [V]`.
114+
//
115+
// Putting the above together we have `[V] = [key] = &[V]` which is a cycle.
116+
// This means that `[key]` is both `&Key`, `&&Key`, `&&&Key`, and so on ad
117+
// infinitum.
118+
119+
#[rustfmt::skip]
120+
pub fn test() {
121+
let mut key_to_key = HashMap::<&Key, &Key>::new(); // $ target=new
122+
let mut key = &Key {}; // Initialize key2 to a reference
123+
if let Some(ref_key) = key_to_key.get(key) { // $ target=get
124+
// Below `ref_key` is implicitly dereferenced from `&&Key` to `&Key`
125+
key = ref_key;
126+
}
127+
key_to_key.insert(key, key); // $ target=insert
128+
}
129+
}
130+
96131
pub fn test() {
97132
explicit_monomorphic_dereference(); // $ target=explicit_monomorphic_dereference
98133
explicit_polymorphic_dereference(); // $ target=explicit_polymorphic_dereference
99134
explicit_ref_dereference(); // $ target=explicit_ref_dereference
100135
explicit_box_dereference(); // $ target=explicit_box_dereference
101136
implicit_dereference(); // $ target=implicit_dereference
137+
implicit_deref_coercion_cycle::test(); // $ target=test
102138
}

0 commit comments

Comments
 (0)